home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / phigs / ptk.lha / ptk / source / library / menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-01  |  100.7 KB  |  3,327 lines

  1. /*----------------------------------------------------------------------------
  2.  
  3. Module name: PHIGS menus utility
  4.  
  5. Author: Karen Wyrwas
  6.  
  7. Function: This module contains the PHIGS utility routines
  8. for menus and high level input tools. They are all built on top of PHIGS.
  9.  
  10. External function list: ptk_createboxmenu, ptk_createboxmenuitem, 
  11. ptk_createusermenu, ptk_createusermenuitem, ptk_drawmenu, ptk_erasemenu, 
  12. ptk_scanmenus, ptk_delmenu, ptk_delmenuitem, ptk_createrotator.
  13.  
  14. Internal function list: getmenu, getmenuid, ptk_findnextpickid, 
  15. find_insertion_pt, find_item, shift_items, delete_item, point_in_menu, 
  16. find_string, string_in_menu, pick_in_menu, disposemenus, get_tlboxcorner, 
  17. insert_box_item, insert_user_item.
  18.  
  19. Hashtables used: "structureid", "name", "label".
  20.  
  21. Modification history: (Version), (Date), (Name), (Description).
  22.  
  23.  1.0, 9th March 1988, Karen Wyrwas, First version.
  24.  
  25.  1.1, 31st October 1988, Karen Wyrwas, Add rotator routines.
  26.  
  27.  1.2, 1st November 1988, Karen Wyrwas, Port to VAX PHIGS.
  28.  
  29.  2.0, 25th April 1991, Gareth Williams, Translated to C.
  30.  
  31.  2.1, 16th May 1991, Gareth Williams, Functions getmenu, getmenuid,
  32.  disposemenus, ptk_inqpickmenus added.
  33.  
  34.  2.2, 23rd May 1991, Gareth Williams, Built rotators on top of user menus.
  35.  
  36.  3.0, June 1992, Gareth Williams, Converted to ISO PHIGS C.
  37.  
  38.  ---------------------------------------------------------------------------*/
  39.  
  40. #include <stdio.h>
  41. #include <math.h>
  42. #include <phigs.h>
  43. #include "ptk.h"
  44.  
  45. /*--------------------------------------------------------------------------*/
  46.  
  47. #define PTKCPOSY 1
  48. #define PTKCNEGY 2
  49. #define PTKCPOSX 4
  50. #define PTKCNEGX 3
  51. #define PTKCPOSZ 5
  52. #define PTKCNEGZ 6
  53.  
  54. /*--------------------------------------------------------------------------*/
  55.  
  56. typedef struct ptksmenu
  57. {
  58.   Pint menuid;
  59.   Pint menustid;
  60.   Pint wsid;
  61.   Pint highlight;
  62.   Pint font;
  63.   Pint menuname;
  64.   Pint_list posted;
  65.  
  66.   ptkemenutype menutype;
  67.   Ptext_path menupath;
  68.   Ppoint menuposition;
  69.   Pfloat charheight;
  70.   Pint maxitem;
  71.   char longstr[255];
  72.   Pint intcolour, edgecolour, tlcolour, brcolour, textcolour;
  73.   Pint htintcolour, htedgecolour, httlcolour, htbrcolour, httextcolour;
  74.   Ppoint framesize;
  75.   Ppoint boxsize;
  76.  
  77.   /* rotator */
  78.   Ppoint bannercentre, bannerbox;
  79.   Pint arrowcolour, arrowedgecolour, bannercolour;
  80.  
  81.   struct ptksmenu *next;
  82. } ptksmenu;
  83.  
  84. typedef struct 
  85. {
  86.   ptkboolean postedmenus;
  87.   ptksmenu *frontptr;
  88.   ptksmenu *backptr;
  89. } ptkswsmenu;
  90.  
  91. /*--------------------------------------------------------------------------*/
  92.  
  93. static ptksmenu *menuptr = NULL;
  94. static ptksmenu *firstmenu = NULL;
  95. static ptksmenu *lastmenu = NULL;
  96.  
  97. static Pint numwsids = 0;
  98. static Pint wsids[10];
  99. static ptkswsmenu wsmenus[10];
  100. static Pint menucount = 0;
  101.  
  102. /*--------------------------------------------------------------------------*/
  103. /*                        utility routines                                  */
  104. /*--------------------------------------------------------------------------*/
  105.  
  106. static void setmenu(C(Pint) menuid)
  107. PreANSI(Pint menuid)
  108. {
  109.   ptksmenu *ptr;
  110.  
  111.   if (firstmenu == NULL)
  112.   {
  113.     menuptr = NULL;
  114.     return;
  115.   }
  116.   ptr = firstmenu;
  117.   while (ptr->menuid != menuid)
  118.   {
  119.     ptr = ptr->next;
  120.     if (ptr == NULL)
  121.     {
  122.       menuptr = NULL;
  123.       return;
  124.     }
  125.   }
  126.   menuptr = ptr;
  127. }  /* setmenu */
  128.  
  129. /*-------------------------------------------------------------------------*/
  130.  
  131. static void findwsid(C(Pint) wsid, C(Pint *) ind)
  132. PreANSI(Pint wsid)
  133. PreANSI(Pint *ind)
  134. {
  135.   Pint i;
  136.  
  137.   *ind = -1;
  138.   for (i = 0; i < numwsids; i++)
  139.     if (wsids[i] == wsid)
  140.       *ind = i;
  141. }  /* findwsid */
  142.  
  143. /*--------------------------------------------------------------------------*/
  144.  
  145. static void checkws(C(Pint) wsid)
  146. PreANSI(Pint wsid)
  147. {
  148.   Pint ind;
  149.  
  150.   findwsid(wsid, &ind);
  151.   if (ind == -1)
  152.   {
  153.     wsids[numwsids] = wsid;
  154.     wsmenus[numwsids].postedmenus = FALSE;
  155.     wsmenus[numwsids].frontptr = NULL;
  156.     wsmenus[numwsids].backptr = NULL;
  157.     numwsids++;
  158.   }
  159. }  /* checkws */
  160.  
  161. /*--------------------------------------------------------------------------*/
  162.  
  163. static ptkboolean getmenuid(C(Pint) menustid, C(Pint *) menuid)
  164. PreANSI(Pint menustid)
  165. PreANSI(Pint *menuid)
  166. {
  167.   ptksmenu *ptr;
  168.  
  169.   ptr = firstmenu;
  170.   while (ptr->menustid != menustid)
  171.   {
  172.     ptr = ptr->next;
  173.     if (ptr == NULL)
  174.       return FALSE;
  175.   }
  176.   *menuid = ptr->menuid;
  177.   return TRUE;
  178. }  /* getmenuid */
  179.  
  180. /*-------------------------------------------------------------------------*/
  181.  
  182. static ptkboolean ismenu(C(Pint) menustid, C(ptksmenu **) mptr)
  183. PreANSI(Pint menustid)
  184. PreANSI(ptksmenu **mptr)
  185. {
  186.   ptksmenu *ptr;
  187.   ptkboolean found;
  188.  
  189.   ptr = firstmenu;
  190.   found = FALSE;
  191.   while ((ptr != NULL) && (!found))
  192.   {
  193.     if (ptr->menustid == menustid)
  194.     {
  195.       *mptr = ptr;
  196.       found = TRUE;
  197.     }
  198.     else
  199.       ptr = ptr->next;
  200.   }
  201.   return found;
  202. }  /* ismenu */
  203.  
  204. /*--------------------------------------------------------------------------*/
  205.  
  206. static void findfront(C(Pint) wsid, C(ptkswsmenu *) wsfront)
  207. PreANSI(Pint wsid)
  208. PreANSI(ptkswsmenu *wsfront)
  209. {
  210.   Pposted_struct_list structlist;
  211.   Pint numstructs, error, i;
  212.   Pfloat priority;
  213.   ptkboolean found;
  214.   ptksmenu *mptr;
  215.  
  216.   priority = 0.0;
  217.   found = FALSE;
  218.   i = 0;
  219.   pinq_posted_structs(wsid, 0, 0, &error, &structlist, &numstructs);
  220.   structlist.postings = (Pposted_struct *)calloc(numstructs, 
  221.                                               sizeof(Pposted_struct));
  222.   pinq_posted_structs(wsid, numstructs, 0, &error, &structlist, &numstructs);
  223.   for (i = 0; i < numstructs; i++)
  224.   {
  225.     /* find highest priority menu structure */
  226.     if (ismenu(structlist.postings[i].id, &mptr))
  227.       if (structlist.postings[i].disp_pri > priority)
  228.       {
  229.         priority = structlist.postings[i].disp_pri;
  230.         wsfront->frontptr = mptr;
  231.         found = TRUE;
  232.       }
  233.   }
  234.   if (!found)
  235.     wsfront->postedmenus = FALSE;
  236. }  /* findfront */
  237.  
  238. /*--------------------------------------------------------------------------*/
  239.  
  240. static void findback(C(Pint) wsid, C(ptkswsmenu *) wsback)
  241. PreANSI(Pint wsid)
  242. PreANSI(ptkswsmenu *wsback)
  243. {
  244.   Pposted_struct_list structlist;
  245.   Pint numstructs, error, i;
  246.   Pfloat priority;
  247.   ptkboolean found;
  248.   ptksmenu *mptr;
  249.  
  250.   priority = 1.0;
  251.   found = FALSE;
  252.   i = 0;
  253.   pinq_posted_structs(wsid, 0, 0, &error, &structlist, &numstructs);
  254.   structlist.postings = (Pposted_struct *)calloc(numstructs, 
  255.                                               sizeof(Pposted_struct));
  256.   pinq_posted_structs(wsid, numstructs, 0, &error, &structlist, &numstructs);
  257.   for (i = 0; i < numstructs; i++)
  258.   {
  259.     /* find lowest priority menu structure */
  260.     if (ismenu(structlist.postings[i].id, &mptr))
  261.       if (structlist.postings[i].disp_pri < priority)
  262.       {
  263.         priority = structlist.postings[i].disp_pri;
  264.         wsback->backptr = mptr;
  265.         found = TRUE;
  266.       }
  267.   }
  268.   if (!found)
  269.     wsback->postedmenus = FALSE;
  270. }  /* findback */
  271.  
  272. /*--------------------------------------------------------------------------*/
  273.  
  274. static void find_insertion_pt(C(Pint) menustid, C(Pint) itemno, 
  275.                C(Pint *) eltptr, C(Pint *) itemfound)
  276. PreANSI(Pint menustid)
  277. PreANSI(Pint itemno)
  278. PreANSI(Pint *eltptr)
  279. PreANSI(Pint *itemfound)
  280. /*
  281. ** \parambegin
  282. ** \param{}{menustid}{menu structure id}{IN}
  283. ** \param{}{itemno}{number of menu item}{IN}
  284. ** \param{}{eltptr}{element pointer of pick id}{IN}
  285. ** \param{}{itemfound}{pick id value}{IN}
  286. ** \paramend
  287. ** \blurb{Search struct for `set pick id' structure elements until 
  288. ** either get to end of structure or a pick id >= `itemno' is found, 
  289. ** in which case the element number of the corresponding structure element 
  290. ** is returned (this is the point at which "itemno" will be inserted). 
  291. ** `itemfound' indicates whether or not the pick id found was `itemno'.
  292. ** Returns TRUE if pick id found, otherwise FALSE.}
  293. */
  294. {
  295.   Pint pickid;
  296.   ptkboolean finished;
  297.  
  298.   finished = FALSE;
  299.   *itemfound = -1;
  300.   *eltptr = 2;
  301.   do
  302.   {
  303.     if (ptk_findnextpickid(menustid, PDIR_FORWARD, eltptr, &pickid))
  304.     {
  305.       if (pickid >= itemno)
  306.       {
  307.         *itemfound = pickid;
  308.          finished = TRUE;
  309.       }
  310.       else
  311.         (*eltptr)++;
  312.     }
  313.     else
  314.     {
  315.       *eltptr = ptk_elemcount(menustid) - 1;
  316.       finished = TRUE;
  317.     }
  318.   } while (!finished);
  319. }  /* find_insertion_pt */
  320.  
  321. /*--------------------------------------------------------------------------*/
  322.  
  323. static void finditemrange(C(Pint) menustid, C(Pint) itemno, 
  324.                C(Pint *) elem1, C(Pint *) elem2)
  325. PreANSI(Pint menustid)
  326. PreANSI(Pint itemno)
  327. PreANSI(Pint *elem1)
  328. PreANSI(Pint *elem2)
  329. /*
  330. ** \parambegin
  331. ** \param{}{menustid}{menu structure id}{IN}
  332. ** \param{}{itemno}{number of menu item}{IN}
  333. ** \param{}{eltptr}{element pointer of pick id}{IN}
  334. ** \param{}{itemfound}{pick id value}{IN}
  335. ** \paramend
  336. ** \blurb{Search struct for `set pick id' structure elements until 
  337. ** either get to end of structure or a pick id >= `itemno' is found, 
  338. ** in which case the element number of the corresponding structure element 
  339. ** is returned (this is the point at which "itemno" will be inserted). 
  340. ** `itemfound' indicates whether or not the pick id found was `itemno'.
  341. ** Returns TRUE if pick id found, otherwise FALSE.}
  342. */
  343. {
  344.   Pint pickid;
  345.   ptkboolean finished;
  346.  
  347.   finished = FALSE;
  348.   *elem1 = 1;
  349.   do
  350.   {
  351.     if (ptk_findnextpickid(menustid, PDIR_FORWARD, elem1, &pickid))
  352.     {
  353.       if (pickid == itemno)
  354.       {
  355.         *elem2 = *elem1 + 1;
  356.         if (ptk_findnextpickid(menustid, PDIR_FORWARD, elem2, &pickid))
  357.     {
  358.           (*elem2)--;
  359.           finished = TRUE;
  360.         }
  361.         else
  362.     {
  363.           *elem2 = ptk_elemcount(menustid) - 2;
  364.           finished = TRUE;
  365.         }
  366.       }
  367.       else 
  368.         (*elem1)++;
  369.     }
  370.     else
  371.     {
  372.       *elem1 = *elem2 = -1;
  373.       finished = TRUE;
  374.     }
  375.   } while (!finished);
  376. }  /* finditemrange */
  377.  
  378. /*--------------------------------------------------------------------------*/
  379.  
  380. static ptkboolean find_item(C(Pint) menustid, C(Pint) itemno, C(Pint *) eltptr)
  381. PreANSI(Pint menustid)
  382. PreANSI(Pint itemno)
  383. PreANSI(Pint *eltptr)
  384. /*
  385. ** \parambegin
  386. ** \param{}{menustid}{menu structure id}{IN}
  387. ** \param{}{itemno}{menu item number}{IN}
  388. ** \param{}{eltptr}{element pointer of pick id}{IN}
  389. ** \paramend
  390. ** \blurb{Look for item in menu.
  391. ** Returns TRUE if item found, otherwise FALSE.}
  392. */
  393. {
  394.   Pint pickid;
  395.   ptkboolean found;
  396.  
  397.   *eltptr = 2;
  398.   found = FALSE;
  399.   do 
  400.   {
  401.     if (ptk_findnextpickid(menustid, PDIR_FORWARD, eltptr, &pickid))
  402.     {
  403.       if (pickid == itemno)
  404.     found = TRUE;
  405.       else 
  406.     (*eltptr)++;
  407.     } 
  408.     else
  409.       *eltptr = -1;
  410.   } while ((!found) && (*eltptr != -1));
  411.   return found;
  412. }  /* find_item */
  413.  
  414. /*--------------------------------------------------------------------------*/
  415.  
  416. static Ppoint3 get_tlboxcorner(C(Pint) itemno)
  417. PreANSI(Pint itemno)
  418. /*
  419. ** \parambegin
  420. ** \param{}{itemno}{menu item number}{IN}
  421. ** \paramend
  422. ** \blurb{Get top left corner of box menu item.
  423. ** Returns top left corner of menu item.}
  424. */
  425. {
  426.   Ppoint3 temp;
  427.  
  428.   temp = ptk_point3(0.0, 0.0, 0.0);
  429.   switch (menuptr->menupath) 
  430.   {
  431.  
  432.   case PPATH_RIGHT:
  433.     temp.x = (Pfloat)(itemno - 1) * menuptr->boxsize.x;
  434.     break;
  435.  
  436.   case PPATH_LEFT:
  437.     temp.x = (Pfloat)(1 - itemno) * menuptr->boxsize.x;
  438.     break;
  439.  
  440.   case PPATH_UP:
  441.     temp.y = (Pfloat)(itemno - 1) * menuptr->boxsize.y;
  442.     break;
  443.  
  444.   case PPATH_DOWN:
  445.     temp.y = (Pfloat)(1 - itemno) * menuptr->boxsize.y;
  446.     break;
  447.   }
  448.   return temp;
  449. }  /* get_tlboxcorner */
  450.  
  451. /*--------------------------------------------------------------------------*/
  452.  
  453. static void shift_items(C(Pint) eltno, C(Pint) shiftby)
  454. PreANSI(Pint eltno)
  455. PreANSI(Pint shiftby)
  456. /*
  457. ** \parambegin
  458. ** \param{}{menustid}{menu structure id}{IN}
  459. ** \param{}{eltno}{element pointer of first pickid in menu}{IN}
  460. ** \param{}{menuinfo}{menu description data}{IN}
  461. ** \param{}{shiftby}{amount to shift boxes}{IN}
  462. ** \paramend
  463. ** \blurb{If menu is a `box' menu, shift subsequent items by size of 
  464. ** box and increment item number.}
  465. */
  466. {
  467.   Pmatrix3 shiftmat;
  468.   Pint pickid;
  469.   ptkboolean end_of_struct;
  470.   Ppoint3 shift;
  471.  
  472.   /* replace subsequent "set pick id" elts with pick id = pick id + shiftby */
  473.   end_of_struct = FALSE;
  474.   if (!ptk_findnextpickid(menuptr->menustid, PDIR_FORWARD, &eltno, &pickid))
  475.     return;
  476.   ptk_seteditmode(PEDIT_REPLACE);
  477.   do 
  478.   {
  479.     pset_elem_ptr(eltno);
  480.     pset_pick_id(pickid + shiftby);
  481.     if (menuptr->menutype == PTKEBOXMENU)
  482.     {
  483.       shift = get_tlboxcorner(pickid + shiftby);
  484.       ptk_shift3(&shift, PTYPE_REPLACE, shiftmat);
  485.       poffset_elem_ptr(1);
  486.       pset_local_tran3(shiftmat, PTYPE_REPLACE);
  487.     }
  488.     eltno++;
  489.     if (!ptk_findnextpickid(menuptr->menustid, PDIR_FORWARD, &eltno, &pickid)) 
  490.       end_of_struct = TRUE;
  491.   } while (!end_of_struct);
  492.   ptk_unseteditmode();
  493. }  /* shift_items */
  494.  
  495. /*--------------------------------------------------------------------------*/
  496.  
  497. static void delete_item(C(Pint) menustid, C(Pint) itemnum)
  498. PreANSI(Pint menustid)
  499. PreANSI(Pint itemnum)
  500. /*
  501. ** \parambegin
  502. ** \param{}{menustid}{menu structure id}{IN}
  503. ** \param{}{eltno}{element pointer of item}{IN}
  504. ** \paramend
  505. ** \blurb{Delete item from menu. }
  506. */
  507. {
  508.   Pint elem1, elem2;
  509.  
  510.   finditemrange(menustid, itemnum, &elem1, &elem2);
  511.   if (elem1 != -1)
  512.   {
  513.     ptk_openstruct(menustid);
  514.     pdel_elem_range(elem1, elem2);
  515.     ptk_closestruct();
  516.   }
  517. }  /* delete_item */
  518.  
  519. /*--------------------------------------------------------------------------*/
  520.  
  521. static ptkboolean find_string(C(Pint) structure, C(Pint *) pickid, 
  522.                            C(char *) str)
  523. PreANSI(Pint structure)
  524. PreANSI(Pint *pickid)
  525. PreANSI(char *str)
  526. /*
  527. ** \parambegin
  528. ** \param{}{structure}{menu structure id}{IN}
  529. ** \param{}{pickid}{item containing string}{IN}
  530. ** \param{}{strmenu}{string and menu data}{IN}
  531. ** \paramend
  532. ** \blurb{Search for string in menu items.
  533. ** Returns TRUE if string found, otherwise FALSE.}
  534. */
  535. {
  536.   Pint error;
  537.   Psearch_status stat;
  538.   ptkselcontent elcont;
  539.   Pstore store;
  540.   Pint eltptr;
  541.   ptkboolean stop_search, string_found;
  542.   Pint numelems;
  543.   Pelem_type_list include, exclude;
  544.   Pelem_type includeelems[10], excludeelems[10];
  545.  
  546.   eltptr = 0;
  547.   stop_search = FALSE;
  548.   string_found = FALSE;
  549.   numelems = ptk_elemcount(structure);
  550.   do 
  551.   {
  552.     includeelems[0] = PELEM_TEXT3;
  553.     includeelems[1] = PELEM_TEXT;
  554.     includeelems[2] = PELEM_EXEC_STRUCT;
  555.     includeelems[3] = PELEM_PICK_ID;
  556.     include.num_elem_types = 4;
  557.     include.elem_types = includeelems;
  558.     exclude.num_elem_types = 0;
  559.     exclude.elem_types = excludeelems;
  560.  
  561.     pelem_search(structure, eltptr, PDIR_FORWARD, &include, &exclude,
  562.                 &error, &stat, &eltptr);
  563.  
  564.     if (error != 0)
  565.       stop_search = TRUE;
  566.     else 
  567.     if (stat != PSEARCH_STATUS_SUCCESS) 
  568.       stop_search = TRUE;
  569.     else 
  570.     {
  571.       pcreate_store(&error, &store);
  572.       ptk_inqelemtypesizecontent(structure, eltptr, store, &error, &elcont);
  573.       if (error == 0) 
  574.       {
  575.         switch (elcont.eltype) 
  576.         {
  577.   
  578.           case PELEM_TEXT:
  579.             if (strcmp(elcont.eldata->text.char_string, str) == 0)
  580.               string_found = TRUE;
  581.             break;
  582.  
  583.           case PELEM_TEXT3:
  584.             if (strcmp(elcont.eldata->text3.char_string, str) == 0)
  585.               string_found = TRUE;
  586.             break;
  587.  
  588.           case PELEM_EXEC_STRUCT:
  589.             string_found = find_string(elcont.eldata->int_data, pickid, str);
  590.             break;
  591.  
  592.           case PELEM_PICK_ID:
  593.             *pickid = elcont.eldata->int_data;
  594.              break;
  595.         }
  596.       }
  597.     }
  598.     eltptr++;
  599.     ptk_delstore(store);
  600.   } while (!string_found && !stop_search && (eltptr <= numelems));
  601.   return string_found;
  602. }  /* find_string */
  603.  
  604. /*--------------------------------------------------------------------------*/
  605.  
  606. static void redrawboxmenuitem(C(Pint) textcolour, C(Pint) intcolour, 
  607.                               C(Pint) edgecolour, C(Pint) tlcolour, 
  608.                               C(Pint) brcolour)
  609. PreANSI(Pint textcolour)
  610. PreANSI(Pint intcolour)
  611. PreANSI(Pint edgecolour)
  612. PreANSI(Pint tlcolour)
  613. PreANSI(Pint brcolour)
  614. {
  615.   Ppoint3 box_centre;
  616.   Pint err, elptr, lstnum;
  617.   Ppoint centresize;
  618.   Pelem_type eltype[2];
  619.   Psearch_status stat;
  620.  
  621.   /* find elem = setintstyle */
  622.   eltype[0] = PELEM_INT_STYLE;
  623.   ptk_findelemtype(eltype, 1, PDIR_FORWARD, &stat, &elptr, &lstnum);
  624.   /* delete next 9 elems */
  625.   ptk_delelem(9);
  626.   box_centre = ptk_point3(0.5 * menuptr->boxsize.x,
  627.           -0.5 * menuptr->boxsize.y, 0.0);
  628.   centresize = ptk_point(menuptr->boxsize.x - 
  629.                          (2.0 * menuptr->framesize.x),
  630.                          menuptr->boxsize.y - 
  631.                          (2.0 * menuptr->framesize.y));
  632.   ptk_framebox(&box_centre, ¢resize, &menuptr->framesize,
  633.                intcolour, edgecolour, tlcolour, brcolour);
  634.   /* replace text colour if required */
  635.   eltype[0] = PELEM_TEXT_COLR_IND;
  636.   eltype[1] = PELEM_PICK_ID;
  637.   ptk_findelemtype(eltype, 2, PDIR_FORWARD, &stat, &elptr, &lstnum);
  638.   if ((stat == PSEARCH_STATUS_SUCCESS) && (lstnum == 0))
  639.   {
  640.     pdel_elem();
  641.     pset_text_colr_ind(textcolour);
  642.   }
  643. }  /* redrawboxmenuitem */
  644.  
  645. /*--------------------------------------------------------------------------*/
  646.  
  647. static void resetcharheight()
  648. {
  649.   ptk_openstruct(menuptr->menustid);
  650.   pset_elem_ptr(0);
  651.   pset_elem_ptr_label(ptk_stringtoint("label", "charheight"));
  652.   poffset_elem_ptr(1);
  653.   pdel_elem();
  654.   pset_char_ht(menuptr->charheight);
  655.   ptk_closestruct();
  656. }  /* resetcharheight */
  657.  
  658. /*--------------------------------------------------------------------------*/
  659.  
  660. static void getmenulimits(C(Ppoint *) pos, C(Plimit *) lims)
  661. PreANSI(Ppoint *pos)
  662. PreANSI(Plimit *lims)
  663. {
  664.   Pfloat xdimen, ydimen;
  665.  
  666.   xdimen = menuptr->boxsize.x; /* + (2.0 * menuptr->framesize.x); */
  667.   ydimen = menuptr->boxsize.y; /* + (2.0 * menuptr->framesize.y); */
  668.   *lims = ptk_limit(pos->x, pos->x, pos->y, pos->y);
  669.   if (menuptr->menutype == PTKEBOXMENU)
  670.     switch (menuptr->menupath)
  671.     {
  672.       case PPATH_RIGHT:
  673.         lims->x_max += ((Pfloat)menuptr->maxitem * xdimen);
  674.         lims->y_min -= ydimen;
  675.         break;
  676.  
  677.       case PPATH_LEFT:
  678.         lims->x_min -= (menuptr->maxitem - 1) * xdimen;
  679.         lims->x_max += xdimen;
  680.         lims->y_min -= ydimen;
  681.         break;
  682.  
  683.       case PPATH_UP:
  684.         lims->x_max += xdimen;
  685.         lims->y_min -= ydimen;
  686.         lims->y_max += ((Pfloat)(menuptr->maxitem - 1) * ydimen);
  687.         break;
  688.  
  689.       case PPATH_DOWN:
  690.         lims->x_max += xdimen;
  691.         lims->y_min -= ((Pfloat)menuptr->maxitem * ydimen);
  692.         break;
  693.     }
  694.   else
  695.   {
  696.     lims->x_max += xdimen / 2.0;
  697.     lims->x_min -= xdimen / 2.0;
  698.     lims->y_max += ydimen / 2.0;
  699.     lims->y_min -= ydimen / 2.0;
  700.   }
  701. }  /* getmenulimits */
  702.  
  703. /*--------------------------------------------------------------------------*/
  704. /*------------------- exported menu routines -------------------------------*/
  705. /*--------------------------------------------------------------------------*/
  706.  
  707. /*function:external*/
  708. extern void ptk_createusermenu(C(Pint) menuid, C(Pint) menustid)
  709. PreANSI(Pint menuid)
  710. PreANSI(Pint menustid)
  711. /*
  712. ** \parambegin
  713. ** \param{Pint}{menuid}{menu identifier}{IN}
  714. ** \param{Pint}{menustid}{menu structure identifier}{IN}
  715. ** \paramend
  716. ** \blurb{This function creates a user menu using the structure
  717. ** {\tt menustid}. Each menu item must be an individual PHIGS
  718. ** structure or network and the menu initially contains no menu items.
  719. ** This function requires hashtables "label", "name".} 
  720. */
  721. {
  722.   ptksmenu *newmenu;
  723.   Pint_list incl;
  724.   Pint inclname;
  725.   char stname[30];
  726.   Pmatrix3 unitmat;
  727.  
  728.   setmenu(menuid);
  729.   if (menuptr == NULL)
  730.   {
  731.     if (lastmenu == NULL)
  732.     {
  733.       firstmenu = lastmenu = newmenu =
  734.         (ptksmenu *)malloc(sizeof(ptksmenu));
  735.       newmenu->next = NULL;
  736.     }
  737.     else
  738.     {
  739.       lastmenu->next = newmenu = (ptksmenu *)malloc(sizeof(ptksmenu));
  740.       newmenu->next = NULL;
  741.       lastmenu = lastmenu->next;
  742.     }
  743.  
  744.     menucount++;  
  745.     newmenu->menuid = menuid;
  746.     newmenu->menustid = menustid;
  747.     newmenu->maxitem = 0;
  748.     newmenu->highlight = 0;
  749.     newmenu->posted.num_ints = 0;
  750.     newmenu->posted.ints = (Pint *)calloc(10, sizeof(Pint));
  751.     sprintf(stname, "name$menu%d", menuid);
  752.     newmenu->menuname = ptk_stringtoint("name", stname);
  753.     ptk_openstruct(newmenu->menustid);
  754.     ptk_seteditmode(PEDIT_INSERT);
  755.     pset_elem_ptr(0);
  756.   
  757.     newmenu->menutype = PTKEUSERMENU;
  758.   
  759.     incl.num_ints = 1;
  760.     incl.ints = &inclname; 
  761.     incl.ints[0] = newmenu->menuname;
  762.   
  763.     plabel(ptk_stringtoint("label", "menuviewind"));
  764.   
  765.     plabel(ptk_stringtoint("label", "globaltran"));
  766.     ptk_unitmatrix3(unitmat);
  767.     pset_global_tran3(unitmat);
  768.  
  769.     padd_names_set(&incl);
  770.     plabel(ptk_stringtoint("label", "begin-menu"));
  771.  
  772.     plabel(ptk_stringtoint("label", "end-menu"));
  773.     premove_names_set(&incl);
  774.     ptk_unseteditmode();
  775.     ptk_closestruct();
  776.   }
  777. }  /* ptk_createusermenu */
  778.  
  779. /*--------------------------------------------------------------------------*/
  780.  
  781. static void createboxmenu(C(Pint) menuid,
  782.             C(Ppoint *) tlcorner, C(Ppoint *) boxsize,
  783.             C(Ptext_path) menupath, C(Pint) textcolour, C(Pint) intcolour, 
  784.             C(Pint) edgecolour, C(Pint) boxtlcolour, C(Pint) boxbrcolour)
  785. PreANSI(Pint menuid)
  786. PreANSI(Ppoint *tlcorner)
  787. PreANSI(Ppoint *boxsize)
  788. PreANSI(Ptext_path menupath)
  789. PreANSI(Pint textcolour)
  790. PreANSI(Pint intcolour)
  791. PreANSI(Pint edgecolour)
  792. PreANSI(Pint boxtlcolour)
  793. PreANSI(Pint boxbrcolour)
  794. /*
  795. ** \parambegin
  796. ** \param{Pint}{menuid}{menu identifier}{IN}
  797. ** \param{Ppoint *}{tlcorner}{top left corner of menu}{IN}
  798. ** \param{Ppoint *}{boxsize}{width and height of menu box item}{IN}
  799. ** \param{Ptext_path}{menupath}{path of box menu (left, right, up, down)}{IN}
  800. ** \param{Pint}{textcolour}{colour index for text}{IN}
  801. ** \param{Pint}{intcolour}{colour index for interior}{IN}
  802. ** \param{Pint}{edgecolour}{colour index for edges}{IN}
  803. ** \param{Pint}{boxtlcolour}{colour index for top-left of box}{IN}
  804. ** \param{Pint}{boxcolour}{colour index for bottom-right of box}{IN}
  805. ** \paramend
  806. ** \blurb{Create a box menu using given specification.}
  807. */
  808. {
  809.   Ptext_align align;
  810.   Pmatrix3 mat;
  811.   ptksmenu *newmenu;
  812.   Pint_list wsids;
  813.   Pint err, totlen, wsid;
  814.   char stname[20], *str;
  815.   Pint_list incl;
  816.   Pint inclname, i, maxchars;
  817.   Pfloat charheight, framedim;
  818.   Ppoint3 pos;
  819.  
  820.   setmenu(menuid);
  821.   if (menuptr == NULL)
  822.   {
  823.     if (lastmenu == NULL)
  824.     {
  825.       firstmenu = lastmenu = newmenu =
  826.         (ptksmenu *)malloc(sizeof(ptksmenu));
  827.       newmenu->next = NULL;
  828.     }
  829.     else
  830.     {
  831.       lastmenu->next = newmenu = (ptksmenu *)malloc(sizeof(ptksmenu));
  832.       newmenu->next = NULL;
  833.       lastmenu = lastmenu->next;
  834.     }
  835.   
  836.     menucount++;
  837.     newmenu->menuid = menuid;
  838.     wsids.ints = &wsid;
  839.     pinq_open_wss(1, 0, &err, &wsids, &totlen);
  840.     newmenu->wsid = wsids.ints[0];
  841.     newmenu->font = 1;
  842.     newmenu->highlight = 0;
  843.     newmenu->posted.num_ints = 0;
  844.     newmenu->posted.ints = (Pint *)calloc(10, sizeof(Pint));
  845.     sprintf(stname, "ptk$menu%d", menuid);
  846.     newmenu->menustid = ptk_stringtoint("structureid", stname);
  847.     sprintf(stname, "name$menu%d", menuid);
  848.     newmenu->menuname = ptk_stringtoint("name", stname);  
  849.     newmenu->menutype = PTKEBOXMENU;
  850.     newmenu->boxsize = *boxsize;
  851.     newmenu->menupath = menupath;
  852.     newmenu->menuposition = *tlcorner;
  853.     newmenu->maxitem = 0;
  854.     newmenu->charheight = 100.0;
  855.     newmenu->longstr[0] = '\0';
  856.     newmenu->intcolour = intcolour;
  857.     newmenu->edgecolour = edgecolour;
  858.     newmenu->tlcolour = boxtlcolour;
  859.     newmenu->brcolour = boxbrcolour;
  860.     newmenu->textcolour = textcolour;
  861.     newmenu->htintcolour = textcolour;
  862.     newmenu->htedgecolour = edgecolour;
  863.     newmenu->httextcolour = intcolour;
  864.     newmenu->httlcolour = boxbrcolour;
  865.     newmenu->htbrcolour = boxtlcolour;
  866.  
  867.     framedim = 0.05 * PTKMIN(boxsize->x, boxsize->y);
  868.     newmenu->framesize = ptk_point(framedim, framedim);
  869.  
  870.     incl.num_ints = 1;
  871.     incl.ints = &inclname;
  872.     incl.ints[0] = newmenu->menuname;
  873.  
  874.     ptk_openstruct(newmenu->menustid);
  875.     ptk_seteditmode(PEDIT_INSERT);
  876.     padd_names_set(&incl);
  877.   
  878.     plabel(ptk_stringtoint("label", "menuviewind"));
  879.  
  880.     plabel(ptk_stringtoint("label", "globaltran"));
  881.     pos = ptk_point3(tlcorner->x, tlcorner->y, 0.0);
  882.     ptk_shift3(&pos, PTYPE_REPLACE, mat);
  883.     pset_global_tran3(mat);      
  884.     /* calculate text expan */
  885.     pset_text_prec(PPREC_STROKE);
  886.     plabel(ptk_stringtoint("label", "charheight"));
  887.     charheight = 0.01;
  888.     pset_char_ht(charheight);
  889.     pset_text_font(1);
  890.     align.hor = PHOR_CTR;
  891.     align.vert = PVERT_HALF;
  892.     pset_text_align(&align);
  893.     plabel(ptk_stringtoint("label", "begin-menu"));
  894.  
  895.     plabel(ptk_stringtoint("label", "end-menu"));
  896.     premove_names_set(&incl);
  897.     ptk_unseteditmode();
  898.     ptk_closestruct();
  899.   }
  900. }  /* createboxmenu */
  901.  
  902. /*--------------------------------------------------------------------------*/
  903.  
  904. /*function:external*/
  905. extern void ptk_createboxmenu(C(Pint) menuid,
  906.             C(Ppoint *) tlcorner, C(Ppoint *) boxsize)
  907. PreANSI(Pint menuid)
  908. PreANSI(Ppoint *tlcorner)
  909. PreANSI(Ppoint *boxsize)
  910. /*
  911. ** \parambegin
  912. ** \param{Pint}{menuid}{menu identifier}{IN}
  913. ** \param{Ppoint *}{tlcorner}{top left corner of menu}{IN}
  914. ** \param{Ppoint *}{boxsize}{width and height of menu box item}{IN}
  915. ** \paramend
  916. ** \blurb{This function creates a box menu with no initial items.
  917. ** The position of the menu is specified by {\tt tlcorner} which
  918. ** defines the top-left corner of the first menu item. The position
  919. ** and size of box menu items are given in the range [0, 1]. The default
  920. ** menu path is DOWN.
  921. ** This function requires hashtables "structureid", "label", "name".} 
  922. */
  923. {
  924.   createboxmenu(menuid, tlcorner, boxsize, PPATH_DOWN, 1, 0, 1, 1, 1);
  925. }  /* ptk_createboxmenu */
  926.  
  927. /*--------------------------------------------------------------------------*/
  928.  
  929. static void insertboxtextitem(C(Pint) eltno, C(char *) str, C(Pint) itemnum)
  930. PreANSI(Pint eltno)
  931. PreANSI(char *str)
  932. PreANSI(Pint itemnum)
  933. /*
  934. ** \parambegin
  935. **  \param{Pint}{eltno}{element pointer}{IN}
  936. **  \param{}{menubox}{menu item description data}{IN}
  937. ** \paramend
  938. ** \blurb{Add item to box menu.}
  939. */
  940. {
  941.   Pmatrix3 matrix, shiftmat;
  942.   Pfloat scl, charheight;
  943.   Ppoint3 box_centre;
  944.   Ppoint3 tlpt;
  945.   Pint err;
  946.   Plimit3 boundbox, itembox;
  947.   Ppoint centresize, txpt;
  948.  
  949.   pset_elem_ptr(eltno);
  950.   pset_pick_id(itemnum);
  951.   tlpt = get_tlboxcorner(itemnum);
  952.   ptk_shift3(&tlpt, PTYPE_REPLACE, shiftmat);
  953.   pset_local_tran3(shiftmat, PTYPE_REPLACE); 
  954.  
  955.   box_centre = ptk_point3(0.5 * menuptr->boxsize.x,
  956.           -0.5 * menuptr->boxsize.y, 0.0);
  957.   centresize = ptk_point(menuptr->boxsize.x - 
  958.                          (2.0 * menuptr->framesize.x),
  959.                          menuptr->boxsize.y - 
  960.                          (2.0 * menuptr->framesize.y));
  961.   ptk_framebox(&box_centre, ¢resize, &menuptr->framesize,
  962.                menuptr->intcolour, menuptr->edgecolour,
  963.                menuptr->tlcolour, menuptr->brcolour);
  964.  
  965.   /* recalculate character height if necessary */
  966.   ptk_computecharheight(menuptr->wsid, str, ¢resize, menuptr->font, 
  967.                         &charheight);
  968.   if (charheight < menuptr->charheight)
  969.   {
  970.     strcpy(menuptr->longstr, str);
  971.     menuptr->charheight = charheight;
  972.     resetcharheight();
  973.   } 
  974.   pset_text_colr_ind(menuptr->textcolour);
  975.   txpt = ptk_point(box_centre.x, box_centre.y);
  976.   ptext(&txpt, str);
  977. }  /* insertboxtextitem */
  978.  
  979. /*--------------------------------------------------------------------------*/
  980.  
  981. /*function:external*/
  982. extern void ptk_createtextmenuitem(C(Pint) menuid, C(char *) str, 
  983.             C(Pint) itemno, C(Pedit_mode) editmode, C(Pint *) error)
  984. PreANSI(Pint menuid)
  985. PreANSI(char *str)
  986. PreANSI(Pint itemno)
  987. PreANSI(Pedit_mode editmode)
  988. PreANSI(Pint *error)
  989. /*
  990. ** \parambegin
  991. ** \param{Pint}{menuid}{menu identifier}{IN}
  992. ** \param{char *}{str}{text string}{IN}
  993. ** \param{Pint}{itemno}{menu item number}{IN}
  994. ** \param{Pedit\_mode}{editmode}{insert or replace menu item.}{IN}
  995. ** \param{Pint *}{error}{error code}{IN}
  996. ** \paramend
  997. ** \blurb{This function creates a box menu item containing the character
  998. ** string {\tt str}. The string is automatically scaled to fit inside
  999. ** the menu item box. This function may only be used with box menus.
  1000. ** The error code = 1 if {\tt menuid} doesn't exist and = 2 if the
  1001. ** menu is not a box menu.}
  1002. */
  1003. {
  1004.   Pint elt;
  1005.   Pint itemalreadythere;
  1006.  
  1007.   /* check menu name supplied, if it has no prefix add current structure 
  1008.   ** prefix.
  1009.   */
  1010.  
  1011.   *error = 0;
  1012.   setmenu(menuid);
  1013.   if (menuptr != NULL)
  1014.   {
  1015.     ptk_seteditmode(PEDIT_INSERT);
  1016.     ptk_openstruct(menuptr->menustid);
  1017.     if (menuptr->menutype != PTKEBOXMENU)
  1018.       *error = 2;
  1019.     else 
  1020.     {
  1021.       find_insertion_pt(menuptr->menustid, itemno, &elt, &itemalreadythere);
  1022.       if (itemalreadythere == itemno) 
  1023.       {
  1024.         if (editmode == PEDIT_INSERT)  /* shift following items up by one */
  1025.           shift_items(elt, 1);
  1026.         else  /* mode is replace, therefore delete old item */
  1027.           delete_item(menuptr->menustid, itemno);
  1028.       }
  1029.       /* add new item before elt */
  1030.       insertboxtextitem(elt - 1, str, itemno);
  1031.       if (itemno > menuptr->maxitem)
  1032.         menuptr->maxitem = itemno;
  1033.     }
  1034.     ptk_closestruct();
  1035.     ptk_unseteditmode();
  1036.   }
  1037.   else
  1038.     *error = 1;
  1039. }  /* ptk_createtextmenuitem */
  1040.  
  1041. /*--------------------------------------------------------------------------*/
  1042.  
  1043. static void insertboxstructitem(C(Pint) eltno, C(Pint) stid, C(Pint) itemnum)
  1044. PreANSI(Pint eltno)
  1045. PreANSI(Pint stid)
  1046. PreANSI(Pint itemnum)
  1047. /*
  1048. ** \parambegin
  1049. **  \param{Pint}{eltno}{element pointer}{IN}
  1050. **  \param{}{menubox}{menu item description data}{IN}
  1051. ** \paramend
  1052. ** \blurb{Add item to box menu.}
  1053. */
  1054. {
  1055.   Pmatrix3 matrix, shiftmat;
  1056.   Pfloat scl, charheight;
  1057.   Ppoint3 box_centre;
  1058.   Ppoint3 tlpt;
  1059.   Pint err;
  1060.   Plimit3 boundbox, itembox;
  1061.   Ppoint centresize, txpt;
  1062.  
  1063.   pset_elem_ptr(eltno);
  1064.   pset_pick_id(itemnum);
  1065.   tlpt = get_tlboxcorner(itemnum);
  1066.   ptk_shift3(&tlpt, PTYPE_REPLACE, shiftmat);
  1067.   pset_local_tran3(shiftmat, PTYPE_REPLACE); 
  1068.   box_centre = ptk_point3(0.5 * menuptr->boxsize.x,
  1069.           -0.5 * menuptr->boxsize.y, 0.0);
  1070.   centresize = ptk_point(menuptr->boxsize.x - 
  1071.                          (2.0 * menuptr->framesize.x),
  1072.                          menuptr->boxsize.y - 
  1073.                          (2.0 * menuptr->framesize.y));
  1074.   ptk_framebox(&box_centre, ¢resize, &menuptr->framesize,
  1075.                menuptr->intcolour, menuptr->edgecolour,
  1076.                menuptr->tlcolour, menuptr->brcolour);
  1077.   if (ptk_boundingbox(stid, &boundbox, TRUE))
  1078.   {
  1079.     itembox = ptk_limit3(0.0, menuptr->boxsize.x, 
  1080.                          -menuptr->boxsize.y, 0.0, 0.0, 1.0);
  1081.     ptk_box3tobox3(&boundbox, &itembox, FALSE, PTYPE_REPLACE, matrix, &err);
  1082.     pset_local_tran3(matrix, PTYPE_PRECONCAT);
  1083.     pexec_struct(stid);
  1084.   }
  1085. }  /* insertboxstructitem */
  1086.  
  1087. /*--------------------------------------------------------------------------*/
  1088.  
  1089. static void insertuseritem(C(Pint) eltno, C(Pint) stid, C(Pint) itemnum)
  1090. PreANSI(Pint eltno)
  1091. PreANSI(Pint stid)
  1092. PreANSI(Pint itemnum)
  1093. /*
  1094. ** \parambegin
  1095. **  \param{Pint}{eltno}{element pointer}{IN}
  1096. ** \param{}{usermenu}{menu item description data}{IN}
  1097. ** \paramend
  1098. ** \blurb{Add user menu item to currently open structure.}
  1099. */
  1100. {
  1101.   ptk_seteditmode(PEDIT_INSERT);
  1102.   pset_elem_ptr(eltno);
  1103.   pset_pick_id(itemnum);
  1104.   pexec_struct(stid);
  1105.   ptk_unseteditmode();
  1106. }  /* insertuseritem */
  1107.  
  1108. /*--------------------------------------------------------------------------*/
  1109.  
  1110. /*function:external*/
  1111. extern void ptk_createstructmenuitem(C(Pint) menuid, C(Pint) structure, 
  1112.             C(Pint) itemno, C(Pedit_mode) editmode, C(Pint *) error)
  1113. PreANSI(Pint menuid)
  1114. PreANSI(Pint structure)
  1115. PreANSI(Pint itemno)
  1116. PreANSI(Pedit_mode editmode)
  1117. PreANSI(Pint *error)
  1118. /*
  1119. ** \parambegin
  1120. ** \param{Pint}{menuid}{menu identifier}{IN}
  1121. ** \param{Pint}{structure}{menu item structure identifier}{IN}
  1122. ** \param{Pint}{itemno}{menu item number}{IN}
  1123. ** \param{Pedit\_mode}{editmode}{insert or replace menu item}{IN}
  1124. ** \param{Pint *}{error}{error code}{IN}
  1125. ** \paramend
  1126. ** \blurb{This function creates a menu item defined by {\tt structure}.
  1127. ** In the case of box menus the structure is mapped into the item box
  1128. ** with aspect ratio preserved. No transformation is applied for user
  1129. ** menu items. The error code = 1 if {\tt menuid} doesn't exist.}
  1130. */
  1131. {
  1132.   Pint elt;
  1133.   Pint itemalreadythere;
  1134.  
  1135.   *error = 0;
  1136.   setmenu(menuid);
  1137.   if (menuptr != NULL)
  1138.   {
  1139.     ptk_openstruct(menuptr->menustid);
  1140.     ptk_seteditmode(PEDIT_INSERT);
  1141.     {
  1142.  
  1143.       find_insertion_pt(menuptr->menustid, itemno, &elt, &itemalreadythere);
  1144.       if (itemalreadythere == itemno) 
  1145.       {
  1146.         if (editmode == PEDIT_INSERT)  /* shift following items up by one */
  1147.           shift_items(elt, 1);
  1148.         else  /* mode is replace, therefore delete old item */
  1149.           delete_item(menuptr->menustid, itemno);
  1150.       }
  1151.       /* add new item before elt */
  1152.       if ((menuptr->menutype == PTKEUSERMENU) || 
  1153.           (menuptr->menutype == PTKEROTATOR))
  1154.         insertuseritem(elt - 1, structure, itemno);
  1155.       else
  1156.         insertboxstructitem(elt - 1, structure, itemno);
  1157.       if (itemno > menuptr->maxitem)
  1158.         menuptr->maxitem = itemno;
  1159.     }
  1160.     ptk_unseteditmode();
  1161.     ptk_closestruct();
  1162.   }
  1163.   else
  1164.     *error = 1;
  1165. }  /* ptk_createstructmenuitem */
  1166.  
  1167. /*--------------------------------------------------------------------------*/
  1168.  
  1169. /*function:external*/
  1170. extern ptkboolean ptk_delmenu(C(Pint) menuid)
  1171. PreANSI(Pint menuid)
  1172. /*
  1173. ** \parambegin
  1174. ** \param{Pint}{menuid}{menu identifier}{IN}
  1175. ** \paramend
  1176. ** \blurb{This function deletes a menu from the PHIGS Toolkit menu store.
  1177. ** The function returns TRUE if {\tt menuid} is deleted, otherwise FALSE.}
  1178. */
  1179. {
  1180.   ptksmenu *ptr, *junk;
  1181.   char stname[20];
  1182.   Pint i;
  1183.  
  1184.   setmenu(menuid);
  1185.   if (menuptr != NULL)
  1186.   {
  1187.     for (i = 0; i < menuptr->posted.num_ints; i++)
  1188.       ptk_unpostmenu(menuptr->posted.ints[i], menuid);
  1189.     pdel_struct(menuptr->menustid);
  1190.     ptr = firstmenu;
  1191.     if (ptr->menuid == menuid)
  1192.     {
  1193.       firstmenu = firstmenu->next;
  1194.       if (lastmenu->menuid == menuid)
  1195.         lastmenu = firstmenu;
  1196.       free(ptr);
  1197.     }
  1198.     else
  1199.     {
  1200.       while (ptr->next->menuid != menuid)
  1201.       {
  1202.         ptr = ptr->next;
  1203.         if (ptr->next == NULL)
  1204.           return FALSE;
  1205.       }
  1206.       junk = ptr->next;
  1207.       ptr->next = junk->next;
  1208.       free(junk);
  1209.       if (ptr->next == NULL)
  1210.         lastmenu = ptr;
  1211.     }
  1212.     /* delete strings */
  1213.     sprintf(stname, "name$menu%d", menuid);
  1214.     ptk_delstring("name", stname);
  1215.     sprintf(stname, "ptk$menu%d", menuid);
  1216.     ptk_delstring("structureid", stname);
  1217.     menucount--;
  1218.     return TRUE;
  1219.   }
  1220.   else
  1221.     return FALSE;
  1222. }  /* ptk_delmenu */
  1223.  
  1224. /*--------------------------------------------------------------------------*/
  1225.  
  1226. /*function:external*/
  1227. extern ptkboolean ptk_delmenuitem(C(Pint) menuid, C(Pint) itemno)
  1228. PreANSI(Pint menuid)
  1229. PreANSI(Pint itemno)
  1230. /*
  1231. ** \parambegin
  1232. ** \param{Pint}{menuid}{menu identifier}{IN}
  1233. ** \param{Pint}{itemno}{menu item to delete}{IN}
  1234. ** \paramend
  1235. ** \blurb{This function deletes the menu item {\tt itemno}.
  1236. ** The function returns TRUE if the menu item is deleted, otherwise FALSE.}
  1237. */
  1238. {
  1239.   Pint elptr, lstnum, err, numelems;
  1240.   Pfloat charheight, minheight;
  1241.   Pstore store;
  1242.   Pelem_type eltype;
  1243.   Psearch_status stat;
  1244.   ptkselcontent elcont;
  1245.   Ppoint centresize;
  1246.  
  1247.   setmenu(menuid);
  1248.   if (menuptr != NULL)
  1249.   {
  1250.     if (!find_item(menuptr->menustid, itemno, &elptr)) 
  1251.     {
  1252.       return FALSE;
  1253.     }
  1254.     ptk_openstruct(menuptr->menustid);
  1255.     delete_item(menuptr->menustid, itemno);
  1256.     shift_items(elptr, -1);
  1257.     ptk_closestruct();
  1258.     if (menuptr->menutype == PTKEBOXMENU)
  1259.     {
  1260.       /* reset charheight to longest item string.
  1261.       ** search for all PELEM_TEXT elements in menu structure and
  1262.       ** set charheight to cater for the longest
  1263.       */
  1264.       numelems = ptk_elemcount(menuptr->menustid);
  1265.       ptk_openstruct(menuptr->menustid);
  1266.       elptr = 0;
  1267.       eltype = PELEM_TEXT;
  1268.       minheight = 100.0;
  1269.       centresize = ptk_point(menuptr->boxsize.x - 
  1270.                            (2.0 * menuptr->framesize.x),
  1271.                            menuptr->boxsize.y - 
  1272.                            (2.0 * menuptr->framesize.y));
  1273.       do
  1274.       {
  1275.         pset_elem_ptr(elptr);
  1276.         ptk_findelemtype(&eltype, 1, PDIR_FORWARD, &stat, &elptr, &lstnum);
  1277.         if (stat == PSEARCH_STATUS_SUCCESS)
  1278.         {
  1279.           pcreate_store(&err, &store);
  1280.           ptk_inqelemtypesizecontent(menuptr->menustid, elptr, store, &err,
  1281.                                    &elcont);
  1282.           ptk_computecharheight(menuptr->wsid, 
  1283.                                 elcont.eldata->text.char_string, 
  1284.                                 ¢resize, menuptr->font, &charheight);
  1285.           if (charheight < minheight)
  1286.           {
  1287.             strcpy(menuptr->longstr, elcont.eldata->text.char_string);
  1288.             minheight = charheight;
  1289.           }
  1290.           ptk_delstore(store);
  1291.         }
  1292.         elptr++;
  1293.       } while ((stat == PSEARCH_STATUS_SUCCESS) && (elptr <= numelems));
  1294.       ptk_closestruct();
  1295.       if (minheight < 100.0)
  1296.       {
  1297.         menuptr->charheight = minheight;
  1298.         resetcharheight();
  1299.       }
  1300.     }
  1301.     return TRUE;
  1302.   }
  1303.   else
  1304.     return FALSE;
  1305. }  /* ptk_delmenuitem */
  1306.  
  1307. /*--------------------------------------------------------------------------*/
  1308.  
  1309. /*function:external*/
  1310. extern void ptk_frontmenu(C(Pint) wsid, C(Pint) menuid)
  1311. PreANSI(Pint wsid)
  1312. PreANSI(Pint menuid)
  1313. /*
  1314. ** \parambegin
  1315. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1316. ** \param{Pint}{menuid}{menu identifier}{IN}
  1317. ** \paramend 
  1318. ** \blurb{This function sets the post priority of the menu structure
  1319. ** so that it is displayed on top of all the other posted menus and
  1320. ** windows.}
  1321. */
  1322. {
  1323.   Pint ind, err, frontwindow, backwindow, frontwindowstid, fronticonstid;
  1324.   ptkboolean windows;
  1325.   ptkewindowstate frontstate, backstate;
  1326.  
  1327.   setmenu(menuid);
  1328.   if (menuptr != NULL)
  1329.   {
  1330.     checkws(wsid);
  1331.     findwsid(wsid, &ind);
  1332.     windows = ptk_inqfrontbackwindowid(wsid, &frontwindow, &frontstate,
  1333.                                        &backwindow, &backstate, &err);
  1334.     if (!wsmenus[ind].postedmenus)
  1335.     {
  1336.       if (windows)
  1337.       {
  1338.         ptk_inqwindowstructid(frontwindow, &frontwindowstid, &fronticonstid,
  1339.                               &err);
  1340.         if (frontstate == PTKEWINDOWOPEN)
  1341.           ptk_postrelative(wsid, menuptr->menustid, PPRI_HIGHER,
  1342.                          frontwindowstid, &err);
  1343.         else
  1344.           ptk_postrelative(wsid, menuptr->menustid, PPRI_HIGHER,
  1345.                          fronticonstid, &err);
  1346.       }
  1347.       else
  1348.         ppost_struct(wsid, menuptr->menustid, 0.0);
  1349.       wsmenus[ind].frontptr = wsmenus[ind].backptr = menuptr;
  1350.       wsmenus[ind].postedmenus = TRUE;
  1351.     }
  1352.     else
  1353.     {
  1354.       ptk_postrelative(wsid, menuptr->menustid, PPRI_HIGHER,
  1355.                        wsmenus[ind].frontptr->menustid, &err);
  1356.       wsmenus[ind].frontptr = menuptr;
  1357.       if (menuptr == wsmenus[ind].backptr)
  1358.         findback(wsid, &wsmenus[ind]);
  1359.     }
  1360.     addtointlst(wsid, &menuptr->posted);
  1361.   }
  1362. }  /* ptk_frontmenu */
  1363.  
  1364. /*--------------------------------------------------------------------------*/
  1365.  
  1366. /*function:external*/
  1367. extern void ptk_backmenu(C(Pint) wsid, C(Pint) menuid)
  1368. PreANSI(Pint wsid)
  1369. PreANSI(Pint menuid)
  1370. /*
  1371. ** \parambegin
  1372. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1373. ** \param{Pint}{menuid}{menu identifier}{IN}
  1374. ** \paramend 
  1375. ** \blurb{This function sets the post priority of the menu structure so
  1376. ** that it is displayed below all other posted menus but in front of
  1377. ** all posted windows.}
  1378. */
  1379. {
  1380.   Pint ind, err, frontwindow, backwindow, frontwindowstid, fronticonstid;
  1381.   ptkboolean windows;
  1382.   ptkewindowstate frontstate, backstate;
  1383.  
  1384.   setmenu(menuid);
  1385.   if (menuptr != NULL)
  1386.   {
  1387.     checkws(wsid);
  1388.     findwsid(wsid, &ind);
  1389.     windows = ptk_inqfrontbackwindowid(wsid, &frontwindow, &frontstate,
  1390.                                        &backwindow, &backstate, &err);
  1391.     if (windows)
  1392.     {
  1393.       ptk_inqwindowstructid(frontwindow, &frontwindowstid, &fronticonstid,
  1394.                             &err);
  1395.       if (frontstate == PTKEWINDOWOPEN)
  1396.         ptk_postrelative(wsid, menuptr->menustid, PPRI_HIGHER,
  1397.                          frontwindowstid, &err);
  1398.       else
  1399.         ptk_postrelative(wsid, menuptr->menustid, PPRI_HIGHER,
  1400.                          fronticonstid, &err);
  1401.     }
  1402.     else
  1403.     if (!wsmenus[ind].postedmenus)
  1404.       ppost_struct(wsid, menuptr->menustid, 0.0);
  1405.     else
  1406.       ptk_postrelative(wsid, menuptr->menustid, PPRI_LOWER,
  1407.                        wsmenus[ind].backptr->menustid, &err);
  1408.     if (!wsmenus[ind].postedmenus)
  1409.     {
  1410.       wsmenus[ind].frontptr = wsmenus[ind].backptr = menuptr;
  1411.       wsmenus[ind].postedmenus = TRUE;
  1412.     }
  1413.     else
  1414.     {
  1415.       wsmenus[ind].backptr = menuptr;
  1416.       if (menuptr == wsmenus[ind].frontptr)
  1417.         findfront(wsid, &wsmenus[ind]);
  1418.     }
  1419.     addtointlst(wsid, &menuptr->posted);
  1420.   }
  1421. }  /* ptk_backmenu */
  1422.  
  1423. /*--------------------------------------------------------------------------*/
  1424.  
  1425. /*function:external*/
  1426. extern void ptk_postmenu(C(Pint) wsid, C(Pint) menuid)
  1427. PreANSI(Pint wsid)
  1428. PreANSI(Pint menuid)
  1429. /*
  1430. ** \parambegin
  1431. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1432. ** \param{Pint}{menuid}{menu identifier}{IN}
  1433. ** \paramend
  1434. ** \blurb{This function posts the menu structure to the workstation
  1435. ** {\tt wsid}. The priority of the menu structure is controlled by the
  1436. ** PHIGS Toolkit menu system to provide an ordered stacking of displayed
  1437. ** menus. When {\tt menuid} is posted it becomes the front menu.} 
  1438. */
  1439. {
  1440.   ptk_frontmenu(wsid, menuid);
  1441. }  /* ptk_postmenu */
  1442.  
  1443. /*--------------------------------------------------------------------------*/
  1444.  
  1445. /*function:external*/
  1446. extern void ptk_unpostmenu(C(Pint) wsid, C(Pint) menuid)
  1447. PreANSI(Pint wsid)
  1448. PreANSI(Pint menuid)
  1449. /*
  1450. ** \parambegin
  1451. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1452. ** \param{Pint}{menuid}{menu identifier}{IN}
  1453. ** \paramend
  1454. ** \blurb{This function unposts a menu structure from the workstation
  1455. ** {\tt wsid}. The front and back menus are updated if necessary.}
  1456. */
  1457. {
  1458.   Pint ind;
  1459.  
  1460.   setmenu(menuid);
  1461.   if (menuptr != NULL)
  1462.   {
  1463.     findwsid(wsid, &ind);
  1464.     punpost_struct(wsid, menuptr->menustid);
  1465.     if (menuptr == wsmenus[ind].backptr)
  1466.       findback(wsid, &wsmenus[ind]);
  1467.     if (menuptr == wsmenus[ind].frontptr)
  1468.       findfront(wsid, &wsmenus[ind]);
  1469.     removefromintlst(wsid, &menuptr->posted);
  1470.   }
  1471. }  /* ptk_unpostmenu */
  1472.  
  1473. /*--------------------------------------------------------------------------*/
  1474.  
  1475. /*function:external*/
  1476. extern void ptk_unpostallmenu(C(Pint) wsid)
  1477. PreANSI(Pint wsid)
  1478. /*
  1479. ** \parambegin
  1480. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1481. ** \param{Pint}{menuid}{menu identifier}{IN}
  1482. ** \paramend
  1483. ** \blurb{This function unposts all menus from the workstation {\tt wsid}.}
  1484. */
  1485. {
  1486.   ptksmenu *ptrmenu;
  1487.  
  1488.   ptrmenu = firstmenu;
  1489.   while (ptrmenu != NULL)
  1490.   {
  1491.     if (inintlst(wsid, &ptrmenu->posted) != -1)
  1492.       ptk_unpostmenu(wsid, ptrmenu->menuid);
  1493.     ptrmenu = ptrmenu->next;
  1494.   }
  1495. }  /* ptk_unpostallmenu */
  1496.  
  1497. /*--------------------------------------------------------------------------*/
  1498.  
  1499. /*function:external*/
  1500. extern ptkboolean ptk_stringscanmenus(C(Pint) wsid, C(char *) str, 
  1501.                                    C(Pint *) menuid, C(Pint *) itemnum)
  1502. PreANSI(Pint wsid)
  1503. PreANSI(char *str)
  1504. PreANSI(Pint *menuid)
  1505. PreANSI(Pint *itemnum)
  1506. /*
  1507. ** \parambegin
  1508. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1509. ** \param{char *}{str}{string}{IN}
  1510. ** \param{Pint *}{menuid}{menu identifier}{OUT}
  1511. ** \param{Pint *}{itemno}{item number}{OUT}
  1512. ** \paramend
  1513. ** \blurb{This function compares the character string {\tt str} with
  1514. ** the items of all posted menus. The comparison begins with the
  1515. ** highest priority menu and works through to the back menu.
  1516. ** User menu items are also searched for text primitives with which to
  1517. ** compare the string. The comparison is case sensitive so that
  1518. ** "item 1" is not the same as "IteM 1".
  1519. ** The function returns TRUE if the string matches a menu item, 
  1520. ** otherwise FALSE.}
  1521. */
  1522. {
  1523.   ptkboolean menufound;
  1524.   Pint_list *menus;
  1525.   ptksmenu *ptrmenu;
  1526.   Pint numstructs, i, err;
  1527.   Pposted_struct_list structlist;
  1528.   Pfilter *invisfilt;
  1529.   Pstore store;
  1530.  
  1531.   menufound = FALSE;
  1532.   structlist.postings = NULL;
  1533.   pinq_posted_structs(wsid, 0, 0, &err, &structlist, &numstructs);
  1534.   structlist.postings = (Pposted_struct *)calloc(numstructs, 
  1535.                                               sizeof(Pposted_struct));
  1536.   pinq_posted_structs(wsid, numstructs, 0, &err, &structlist, &numstructs);
  1537.  
  1538.   /* inquire invisibility filter */
  1539.   pcreate_store(&err, &store);
  1540.   pinq_invis_filter(wsid, store, &err, &invisfilt);
  1541.  
  1542.   /* This bit is a bit dodgy because it relies on structlist being ordered
  1543.   ** by PHIGS into highest priority last. This is not standard PHIGS,
  1544.   ** so if version is not sorted do a sort.
  1545.   */
  1546.   i = numstructs - 1;
  1547.   while ((i >= 0) && (!menufound)) 
  1548.   {
  1549.     if (ismenu(structlist.postings[i].id, &ptrmenu))
  1550.     {
  1551.       /* check invisibility filter */
  1552.       if (!((inintlst(ptrmenu->menuname, &invisfilt->incl_set) != -1) && 
  1553.           (inintlst(ptrmenu->menuname, &invisfilt->excl_set) == -1)))
  1554.       {
  1555.         if (find_string(ptrmenu->menustid, itemnum, str))
  1556.         {
  1557.           menufound = TRUE;
  1558.           *menuid = ptrmenu->menuid;
  1559.         }
  1560.       }
  1561.     }
  1562.     i--;
  1563.   }
  1564.   free(structlist.postings);
  1565.   ptk_delstore(store);
  1566.   return menufound;
  1567. }  /* ptk_stringscanmenus */
  1568.  
  1569. /*--------------------------------------------------------------------------*/
  1570.  
  1571. /*function:external*/
  1572. extern ptkboolean ptk_pickscanmenus(C(Ppick_path *) pickpath, 
  1573.             C(Ppath_order) pathorder, C(Pint *) menuid, C(Pint *) itemnum)
  1574. PreANSI(Ppick_path *pickpath)
  1575. PreANSI(Ppath_order pathorder)
  1576. PreANSI(Pint *menuid)
  1577. PreANSI(Pint *itemnum)
  1578. /*
  1579. ** \parambegin
  1580. ** \param{Ppick\_path *}{pickpath}{path through structure network.}{IN}
  1581. ** \param{Ppath\_order}{pathorder}{order of data in pickpath}{IN}
  1582. ** \param{Pint *}{menuid}{menu identifier}{OUT}
  1583. ** \param{Pint *}{itemnum}{item number}{OUT}
  1584. ** \paramend
  1585. ** \blurb{This function tests the pick path to inquire if a menu item
  1586. ** was picked. 
  1587. ** The function returns TRUE if a menu item was picked, otherwise FALSE.}
  1588. */
  1589. {
  1590.   Pint menustid;
  1591.  
  1592.   if (pathorder == PORDER_TOP_FIRST)
  1593.   {
  1594.     *itemnum = pickpath->path_list[pickpath->depth - 1].pick_id;
  1595.     menustid = pickpath->path_list[0].struct_id;
  1596.     return (getmenuid(menustid, menuid));
  1597.   }
  1598.   else
  1599.   {
  1600.     *itemnum = pickpath->path_list[0].pick_id;
  1601.     menustid = pickpath->path_list[pickpath->depth - 1].struct_id;
  1602.     return (getmenuid(menustid, menuid));
  1603.   }
  1604. }  /* ptk_pickscanmenus */
  1605.  
  1606. /*--------------------------------------------------------------------------*/
  1607.  
  1608. /*function:external*/
  1609. extern ptkboolean ptk_locscanmenus(C(Pint) wsid, C(Ppoint *) point, 
  1610.            C(Pint *) menuid, C(Pint *) itemnum, C(Ppoint *) value)
  1611. PreANSI(Pint wsid)
  1612. PreANSI(Ppoint *point)
  1613. PreANSI(Pint *menuid)
  1614. PreANSI(Pint *itemnum)
  1615. PreANSI(Ppoint *value)
  1616. /*
  1617. ** \parambegin
  1618. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1619. ** \param{Ppoint *}{point}{input point}{IN}
  1620. ** \param{Pint *}{menuid}{menu identifier}{OUT}
  1621. ** \param{Pint *}{itemnum}{item number}{OUT}
  1622. ** \param{Ppoint *}{value}{position of point within item}{OUT}
  1623. ** \paramend
  1624. ** \blurb{This function uses the INCREMENTAL SPATIAL SEARCH function 
  1625. ** of PHIGS to test if {\tt point} lies within a posted menu.
  1626. ** The menus are tested begining the highest priority menu and working 
  1627. ** through to the back menu. The position of {\tt point} relative
  1628. ** to bottom-left corner of the menu item bounding box is returned
  1629. ** in {\tt value}.
  1630. ** The function returns TRUE if {\tt point} lies within a menu, 
  1631. ** otherwise FALSE.}
  1632. */
  1633. {
  1634.   /* Implementation dependent code because HP doesn't support
  1635.   ** INCREMENTAL SPATIAL SEARCH. For HP simulate the search by 
  1636.   ** using bounding boxes.
  1637.   */
  1638.   ptkboolean menufound, itemfound;
  1639.   ptksmenu *ptrmenu;
  1640.   Pint foundstruct;
  1641.   Pint elemno, pickid, firstpick, nextpick, nextpickid;
  1642.   Pfloat div;
  1643.   Plimit3 menubox;
  1644.   Pelem_type extype;
  1645.   Psearch_status status;
  1646.   Pint ptrlist[2];
  1647.   Pint_list elemlist;
  1648.   Pint numstructs, i, err;
  1649.   Pposted_struct_list structlist;
  1650.   Ppoint3 minbox, maxbox;
  1651.   Pmatrix3 mat;
  1652.   Pstore store;
  1653.   Pfilter *invisfilt;
  1654. #ifdef SUN
  1655.   Pelem_ref_list reflist, startlist;
  1656.   Pelem_ref startpath;
  1657.   Pint ceiling;
  1658.   Pfilter_list normal, invert;
  1659.   Pfilter filter;
  1660.   Pfloat distance;
  1661.   Pint totlen, len;
  1662.   
  1663.   startlist.num_elem_refs = 1;
  1664.   startlist.elem_refs = &startpath;
  1665.   startpath.elem_pos = 0;
  1666.   ceiling = 1;     /* all of structure network */
  1667.   normal.num_filters = 1;
  1668.   normal.filters = &filter;
  1669.   filter.incl_set.num_ints = 1;
  1670.   filter.excl_set.num_ints = 0;
  1671.   filter.excl_set.ints = NULL;
  1672.   invert.num_filters = 0;
  1673.   invert.filters = NULL;
  1674.   distance = 0.001; /* nearness to point */
  1675.   reflist.num_elem_refs = 0;
  1676.   reflist.elem_refs = NULL;
  1677. #endif
  1678.   ptk_stacktsl();
  1679.   ptk_stackbbox();
  1680.   menufound = FALSE;
  1681.   structlist.postings = NULL;
  1682.   /* inquire posted structures */
  1683.   pinq_posted_structs(wsid, 0, 0, &err, &structlist, &numstructs);
  1684.   structlist.postings = (Pposted_struct *)calloc(numstructs, 
  1685.                                               sizeof(Pposted_struct));
  1686.   pinq_posted_structs(wsid, numstructs, 0, &err, &structlist, &numstructs);
  1687.  
  1688.   /* inquire invisibility filter */
  1689.   pcreate_store(&err, &store);
  1690.   pinq_invis_filter(wsid, store, &err, &invisfilt);
  1691.  
  1692.   /* This bit is a bit dodgy because it relies on structlist being ordered
  1693.   ** by PHIGS into highest priority last. This is not standard PHIGS,
  1694.   ** so if version is not sorted do a sort.
  1695.   ** HP orders with highest priority first.
  1696.   ** PEXSI orders same as SUN.
  1697.   */
  1698. #ifndef HP
  1699.   /* do for SUN and PEXSI */
  1700.   i = numstructs - 1;
  1701.   while ((i >= 0) && (!menufound)) 
  1702. #endif
  1703. #ifdef HP
  1704.   i = 0;
  1705.   while ((i < numstructs) && (!menufound)) 
  1706. #endif
  1707.   {
  1708.     if (ismenu(structlist.postings[i].id, &ptrmenu))
  1709.     {
  1710.       /* check invisibility filter */
  1711.       if (!((inintlst(ptrmenu->menuname, &invisfilt->incl_set) != -1) && 
  1712.             (inintlst(ptrmenu->menuname, &invisfilt->excl_set) == -1)))
  1713.       {
  1714. #ifdef SUN
  1715.         startpath.struct_id = ptrmenu->menustid;
  1716.         filter.incl_set.ints = &ptrmenu->menuname;        
  1717.  
  1718.         pincr_spa_search(point, distance, &startlist, PIND_NO_CLIP,
  1719.                          ceiling, &normal, &invert, 0, 0, &err, 
  1720.                          &reflist, &totlen);
  1721.         reflist.elem_refs = (Pelem_ref *)calloc(totlen, sizeof(Pelem_ref));
  1722.         pincr_spa_search(point, distance, &startlist, PIND_NO_CLIP,
  1723.                          ceiling, &normal, &invert, totlen, 0, &err, 
  1724.                          &reflist, &totlen);
  1725.         *itemnum = 0;
  1726.         if (reflist.num_elem_refs > 0)
  1727.         {
  1728.           menufound = TRUE;
  1729.           *menuid = ptrmenu->menuid;
  1730.           *value = ptk_point(0.0, 0.0);
  1731.           foundstruct = reflist.elem_refs[0].struct_id;
  1732.           elemno = reflist.elem_refs[0].elem_pos;    
  1733.           if (ptk_findnextpickid(foundstruct, PDIR_BACKWARD, &elemno, 
  1734.                                  &pickid))
  1735.             *itemnum = pickid;
  1736.           firstpick = 1;
  1737.           ptk_findnextpickid(foundstruct, PDIR_FORWARD, &firstpick, &pickid);
  1738.  
  1739.           /* inquire TSL from element 1 to firstpick in foundstruct */
  1740.           ptk_inittsl();
  1741.           ptk_tsltraverserange(foundstruct, 1, foundstruct, firstpick, FALSE);
  1742.           nextpick = elemno + 1;
  1743.           if (!ptk_findnextpickid(foundstruct, PDIR_FORWARD, &nextpick, 
  1744.                                   &pickid))
  1745.             nextpick = ptk_elemcount(foundstruct);
  1746.           ptk_initbbox();
  1747.           ptk_tsltraverserange(foundstruct, elemno, foundstruct, nextpick, 
  1748.                                TRUE);
  1749.       ptk_inqboundingbox(&menubox);
  1750.           /* calculate value */
  1751.           div = menubox.x_max - menubox.x_min;
  1752.           if (div != 0.0)
  1753.             value->x = (point->x - menubox.x_min)/div;
  1754.           div = menubox.y_max - menubox.y_min;
  1755.           if (div != 0.0)
  1756.             value->y = (point->y - menubox.y_min)/div;
  1757.           free(reflist.elem_refs);
  1758.         }
  1759. #endif
  1760. #ifndef SUN
  1761.         /* do for HP and PEXSI */
  1762.         foundstruct = ptrmenu->menustid;
  1763.         elemno = firstpick = 1;
  1764.         ptk_findnextpickid(foundstruct, PDIR_FORWARD, &firstpick, &pickid);
  1765.         ptk_inittsl();
  1766.         ptk_tsltraverserange(foundstruct, 1, foundstruct, firstpick, FALSE);
  1767.         ptk_boundingbox(foundstruct, &menubox, TRUE);
  1768.         if (ptinlimit3(point, &menubox))
  1769.         {
  1770.           menufound = TRUE;
  1771.           *menuid = ptrmenu->menuid;
  1772.           itemfound = FALSE;
  1773.           while (!itemfound)
  1774.       {
  1775.         ptk_stacktsl();
  1776.             ptk_stackbbox();
  1777.             if (ptk_findnextpickid(foundstruct, PDIR_FORWARD, &elemno, 
  1778.                 &pickid))
  1779.         {
  1780.               elemlist.num_ints = 2;
  1781.               elemlist.ints = ptrlist;
  1782.               ptrlist[0] = elemno;
  1783.               nextpick = elemno + 1;
  1784.               if (!ptk_findnextpickid(foundstruct, PDIR_FORWARD, &nextpick, 
  1785.                                    &nextpickid))
  1786.                 nextpick = ptk_elemcount(foundstruct);
  1787.               ptk_initbbox();
  1788.               ptk_tsltraverserange(foundstruct, elemno, foundstruct, 
  1789.                                    nextpick, TRUE);
  1790.               ptk_inqboundingbox(&menubox);
  1791.               if (ptinlimit3(point, &menubox))
  1792.           {
  1793.                 itemfound = TRUE;
  1794.                 *itemnum = pickid;         
  1795.                 /* calculate value */
  1796.                 *value = ptk_point(0.0, 0.0);
  1797.                 div = menubox.x_max - menubox.x_min;
  1798.                 if (div != 0.0)
  1799.                   value->x = (point->x - menubox.x_min)/div;
  1800.                 div = menubox.y_max - menubox.y_min;
  1801.                 if (div != 0.0)
  1802.                   value->y = (point->y - menubox.y_min)/div;
  1803.               }
  1804.               else
  1805.                 elemno++;
  1806.             }
  1807.             else
  1808.         {
  1809.               itemfound = TRUE;
  1810.               *itemnum = 0;
  1811.             }         
  1812.             ptk_unstackbbox();
  1813.             ptk_unstacktsl();
  1814.           }
  1815.         }
  1816. #endif
  1817.       }
  1818.     }
  1819. #ifndef HP
  1820.     /* do for SUN and PEXSI */
  1821.     i--;
  1822. #endif
  1823. #ifdef HP
  1824.     i++;
  1825. #endif
  1826.   }
  1827.   free(structlist.postings);
  1828.   ptk_delstore(store);
  1829.   ptk_unstackbbox();
  1830.   ptk_unstacktsl();
  1831.   return menufound; 
  1832. }  /* ptk_locscanmenus */
  1833.  
  1834. /*--------------------------------------------------------------------------*/
  1835.  
  1836. /*function:external*/
  1837. extern ptkboolean ptk_scanmenus(C(Pint) wsid, C(ptksgeneralinput *) input, 
  1838.                              C(ptksmenuoutput *) output)
  1839. PreANSI(Pint wsid)
  1840. PreANSI(ptksgeneralinput *input)
  1841. PreANSI(ptksmenuoutput *output)
  1842. /*
  1843. ** \parambegin
  1844. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1845. ** \param{ptksgeneralinput *}{input}{input data}{IN}
  1846. ** \param{ptksmenuoutput *}{output}{output data}{IN}
  1847. ** \paramend
  1848. ** \blurb{This function performs a scan on all posted menus using
  1849. ** either string, pick or locator data.
  1850. ** The function returns TRUE if a menu item has been selected, 
  1851. ** otherwise FALSE.}
  1852. */
  1853. {
  1854.   ptkboolean result;
  1855.  
  1856.   switch (input->inputclass) 
  1857.   {
  1858.  
  1859.   case PIN_LOC:
  1860.     result = ptk_locscanmenus(wsid, &input->ptkugeninput.locpoint, 
  1861.                            &output->menuid, &output->itemnum, &output->value);
  1862.     output->measure = TRUE;
  1863.     break;
  1864.  
  1865.   case PIN_STROKE:
  1866.     result = FALSE;
  1867.     break;
  1868.  
  1869.   case PIN_VAL:
  1870.     result = FALSE;
  1871.     break;
  1872.  
  1873.   case PIN_CHOICE:
  1874.     result = FALSE;
  1875.     break;
  1876.  
  1877.   case PIN_PICK:
  1878.     result = ptk_pickscanmenus(&input->ptkugeninput.ptkspickinput.pickdata, 
  1879.                           input->ptkugeninput.ptkspickinput.pathorder,
  1880.                           &output->menuid, &output->itemnum);
  1881.     output->measure = FALSE;
  1882.     break;
  1883.  
  1884.   case PIN_STRING:
  1885.     result = ptk_stringscanmenus(wsid, input->ptkugeninput.str, 
  1886.                                  &output->menuid, &output->itemnum);
  1887.     output->measure = FALSE;
  1888.     break;
  1889.   }
  1890.   return result;
  1891. }  /* ptk_scanmenus */
  1892.  
  1893. /*--------------------------------------------------------------------------*/
  1894.  
  1895. /*function:external*/
  1896. extern void ptk_setmenuposition(C(Pint) menuid, C(Ppoint *) menupos)
  1897. PreANSI(Pint menuid)
  1898. PreANSI(Ppoint *menupos)
  1899. /*
  1900. ** \parambegin
  1901. ** \param{Pint}{menuid}{menu identifier}{IN}
  1902. ** \param{Ppoint *}{menupos}{menu position}{IN}
  1903. ** \paramend
  1904. ** \blurb{This function sets the position of the top-left corner of the
  1905. ** first menu item. The position is given in the range [0, 1]. If the
  1906. ** position results in part of the menu being clipped then the actual
  1907. ** position is adjusted so that as much as possible of the menu is 
  1908. ** visible.}
  1909. */
  1910. {
  1911.   Ppoint pos;
  1912.   Ppoint3 mpos;
  1913.   Pmatrix3 mat;
  1914.   Plimit lim;
  1915.  
  1916.   pos = *menupos;
  1917.   setmenu(menuid);
  1918.   if (menuptr != NULL)
  1919.   {
  1920.     if ((menuptr->menutype == PTKEBOXMENU) || 
  1921.         (menuptr->menutype == PTKEROTATOR)) 
  1922.     {
  1923.       getmenulimits(menupos, &lim);
  1924.       if ((lim.x_min < 0.0) && (lim.x_max > 1.0))
  1925.       {  /* do nothing */ }
  1926.       else
  1927.       if ((lim.y_min < 0.0) && (lim.y_max > 1.0))
  1928.       {  /* do nothing */ }
  1929.       else
  1930.       if ((lim.x_min < 0.0) && (lim.y_min < 0.0))
  1931.       {
  1932.         /* bottom left */
  1933.         pos.x += PTKMIN(1.0 - lim.x_max, -lim.x_min);
  1934.         pos.y += PTKMIN(1.0 - lim.y_max, -lim.y_min);
  1935.       }
  1936.       else
  1937.       if ((lim.x_min < 0.0) && (lim.y_max > 1.0))
  1938.       {
  1939.         /* top left */
  1940.         pos.x += PTKMIN(1.0 - lim.x_max, -lim.x_min);
  1941.         pos.y -= PTKMIN(lim.y_min, lim.y_max - 1.0);
  1942.       }
  1943.       else
  1944.       if ((lim.x_max > 1.0) && (lim.y_min < 0.0))
  1945.       {
  1946.         /* bottom right */
  1947.         pos.x -= PTKMIN(lim.x_min, lim.x_max - 1.0);
  1948.         pos.y += PTKMIN(1.0 - lim.y_max, -lim.y_min);
  1949.       }
  1950.       else
  1951.       if ((lim.x_max > 1.0) && (lim.y_max > 1.0))
  1952.       {
  1953.         /* top right */
  1954.         pos.x -= PTKMIN(lim.x_min, lim.x_max - 1.0);
  1955.         pos.y -= PTKMIN(lim.y_min, lim.y_max - 1.0);
  1956.       }
  1957.       else 
  1958.       if (lim.x_min < 0.0)
  1959.         pos.x += PTKMIN(1.0 - lim.x_max, -lim.x_min);
  1960.       else
  1961.       if (lim.x_max > 1.0)
  1962.         pos.x -= PTKMIN(lim.x_min, lim.x_max - 1.0);
  1963.       else
  1964.       if (lim.y_min < 0.0)
  1965.         pos.y += PTKMIN(1.0 - lim.y_max, -lim.y_min);
  1966.       else
  1967.       if (lim.y_max > 1.0)
  1968.         pos.y -= PTKMIN(lim.y_min, lim.y_max - 1.0);
  1969.     }
  1970.     ptk_openstruct(menuptr->menustid);
  1971.     pset_elem_ptr(0);
  1972.     pset_elem_ptr_label(ptk_stringtoint("label", "globaltran"));
  1973.     poffset_elem_ptr(1);
  1974.     pdel_elem();
  1975.     mpos = ptk_point3(pos.x, pos.y, 0.0);
  1976.     ptk_shift3(&mpos, PTYPE_REPLACE, mat);
  1977.     pset_global_tran3(mat);      
  1978.     ptk_closestruct();
  1979.     menuptr->menuposition = pos;
  1980.   }
  1981. }  /* ptk_setmenuposition */
  1982.  
  1983. /*--------------------------------------------------------------------------*/
  1984.  
  1985. /*function:external*/
  1986. extern void ptk_setboxmenutextfont(C(Pint) wsid, C(Pint) menuid, 
  1987.                                    C(Pint) font)
  1988. PreANSI(Pint wsid)
  1989. PreANSI(Pint menuid)
  1990. PreANSI(Pint font)
  1991. /*
  1992. ** \parambegin
  1993. ** \param{Pint}{wsid}{workstation identifier}{IN}
  1994. ** \param{Pint}{menuid}{menu identifier}{IN}
  1995. ** \param{Pint}{font}{text font}{IN}
  1996. ** \paramend
  1997. ** \blurb{This function sets the text font of all text menu items in the
  1998. ** menu structure. The menu must be a box menu.}
  1999. */
  2000. {
  2001.   Ppoint pt;
  2002.   Pfloat charheight;
  2003.  
  2004.   setmenu(menuid);
  2005.   if (menuptr != NULL)
  2006.   {
  2007.     if (menuptr->menutype == PTKEBOXMENU)
  2008.     {
  2009.       menuptr->wsid = wsid;
  2010.       menuptr->font = font;
  2011.       ptk_openstruct(menuptr->menustid);
  2012.       pset_elem_ptr(0);
  2013.       pset_elem_ptr_label(ptk_stringtoint("label", "charheight"));
  2014.       poffset_elem_ptr(2);
  2015.       pdel_elem();
  2016.       pset_text_font(font);
  2017.       ptk_closestruct();
  2018.       if (menuptr->longstr[0] != '\0')
  2019.       {
  2020.         pt = ptk_point(menuptr->boxsize.x - 
  2021.                        (2.0 * menuptr->framesize.x), 
  2022.                        menuptr->boxsize.y -
  2023.                        (2.0 * menuptr->framesize.y)); 
  2024.         ptk_computecharheight(menuptr->wsid, menuptr->longstr,  
  2025.                             &pt, menuptr->font, &charheight);
  2026.         if (charheight < menuptr->charheight)
  2027.         {
  2028.           menuptr->charheight = charheight;
  2029.           ptk_openstruct(menuptr->menustid);
  2030.           pset_elem_ptr(0);
  2031.           pset_elem_ptr_label(ptk_stringtoint("label", "charheight"));
  2032.           poffset_elem_ptr(1);
  2033.           pdel_elem();
  2034.           pset_char_ht(charheight);
  2035.           ptk_closestruct();
  2036.         } 
  2037.       }
  2038.     }
  2039.   }
  2040. }  /* ptk_setboxmenutextfont */
  2041.  
  2042. /*--------------------------------------------------------------------------*/
  2043.  
  2044. /*function:external*/
  2045. extern void ptk_setboxmenuattrs(C(Pint) wsid, C(Pint) menuid, 
  2046.             C(Ptext_path) menupath, C(Pint) font, C(Pint) textcolour, 
  2047.             C(Pint) intcolour, C(Pint) edgecolour, C(Pint) boxtlcolour, 
  2048.             C(Pint) boxbrcolour, C(Pint) httextcolour, 
  2049.             C(Pint) htintcolour, C(Pint) htedgecolour)
  2050. PreANSI(Pint wsid)
  2051. PreANSI(Pint menuid)
  2052. PreANSI(Ptext_path menupath)
  2053. PreANSI(Pint font)
  2054. PreANSI(Pint textcolour)
  2055. PreANSI(Pint intcolour)
  2056. PreANSI(Pint edgecolour)
  2057. PreANSI(Pint boxtlcolour)
  2058. PreANSI(Pint boxbrcolour)
  2059. PreANSI(Pint httextcolour)
  2060. PreANSI(Pint htintcolour)
  2061. PreANSI(Pint htedgecolour) 
  2062. /*
  2063. ** \parambegin
  2064. ** \param{Pint}{wsid}{workstation identifier}{IN}
  2065. ** \param{Pint}{menuid}{menu identifier}{IN}
  2066. ** \param{Ptext\_path}{menupath}{path of box menu (left, right, up, down)}{IN}
  2067. ** \param{Pint}{font}{text font}{IN}
  2068. ** \param{Pint}{textcolour}{colour index for text}{IN}
  2069. ** \param{Pint}{intcolour}{colour index for interior}{IN}
  2070. ** \param{Pint}{edgecolour}{colour index for edges}{IN}
  2071. ** \param{Pint}{boxtlcolour}{colour index for top-left of box}{IN}
  2072. ** \param{Pint}{boxcolour}{colour index for bottom-right of box}{IN}
  2073. ** \param{Pint}{httextcolour}{colour index for highlight text}{IN}
  2074. ** \param{Pint}{htintcolour}{colour index for highlight interior}{IN}
  2075. ** \param{Pint}{htedgecolour}{colour index for highlight edges}{IN}
  2076. ** \paramend
  2077. ** \blurb{This function sets the box menu path, text font and colour attribute
  2078. ** values. The highlight colour indicies are used by the function
  2079. ** {\tt ptk\_setboxmenuhighlightitem} to highlight a single menu item.}
  2080. */
  2081. {
  2082.   Ppoint pt;
  2083.   Pfloat charheight;
  2084.   Pint elptr, lstnum, intstate, err, itemnum;
  2085.   Pelem_type elemlist[3];
  2086.   Psearch_status srchstatus;
  2087.   ptkselcontent elcont;
  2088.   Pmatrix3 shiftmat;
  2089.   Ppoint3 tlpt;
  2090.   Pstore store;
  2091.  
  2092.   setmenu(menuid);
  2093.   if (menuptr != NULL)
  2094.   {
  2095.     if (menuptr->menutype == PTKEBOXMENU)
  2096.     {
  2097.       menuptr->wsid = wsid;
  2098.       menuptr->font = font;
  2099.       menuptr->menupath = menupath;
  2100.       menuptr->intcolour = intcolour;
  2101.       menuptr->edgecolour = edgecolour;
  2102.       menuptr->tlcolour = boxtlcolour;
  2103.       menuptr->brcolour = boxbrcolour;
  2104.       menuptr->textcolour = textcolour;
  2105.       menuptr->httlcolour = boxbrcolour;
  2106.       menuptr->htbrcolour = boxtlcolour;
  2107.       menuptr->htintcolour = htintcolour;
  2108.       menuptr->htedgecolour = htedgecolour;
  2109.       menuptr->httextcolour = httextcolour;
  2110.  
  2111.       /* set colours */
  2112.       ptk_openstruct(menuptr->menustid);
  2113.       pset_elem_ptr(0);
  2114.       pset_elem_ptr_label(ptk_stringtoint("label", "begin-menu"));
  2115.       
  2116.       /* replace all edges, text and interior (in special order) */
  2117.       elemlist[0] = PELEM_EDGE_COLR_IND;
  2118.       elemlist[1] = PELEM_TEXT_COLR_IND;
  2119.       elemlist[2] = PELEM_INT_COLR_IND;
  2120.       intstate = 1;
  2121.       do
  2122.       {
  2123.         ptk_findelemtype(elemlist, 3, PDIR_FORWARD, &srchstatus, &elptr, &lstnum);
  2124.         if (srchstatus == PSEARCH_STATUS_SUCCESS)
  2125.     {
  2126.           pset_elem_ptr(elptr);
  2127.           ptk_seteditmode(PEDIT_REPLACE);
  2128.           switch (lstnum)
  2129.       {
  2130.             case 0: /* PELEM_EDGE_COLR_IND */
  2131.               pset_edge_colr_ind(menuptr->edgecolour);
  2132.               break;
  2133.  
  2134.             case 1: /* PELEM_TEXT_COLR_IND */
  2135.               pset_text_colr_ind(menuptr->textcolour);
  2136.               break;
  2137.  
  2138.             case 2: /* PELEM_INT_COLR_IND */
  2139.               switch (intstate)
  2140.           {
  2141.                 case 1: /* top-left edge */
  2142.                   pset_int_colr_ind(menuptr->tlcolour);
  2143.                   break;
  2144.  
  2145.                 case 2: /* bottom-right edge */
  2146.                   pset_int_colr_ind(menuptr->brcolour);
  2147.                   break;
  2148.  
  2149.                 case 3: /* box */
  2150.                   pset_int_colr_ind(menuptr->intcolour);
  2151.                   break;
  2152.               }
  2153.               intstate++;
  2154.               if (intstate == 4)
  2155.                 intstate = 1;
  2156.               break;
  2157.           }
  2158.           ptk_unseteditmode();
  2159.           poffset_elem_ptr(1);
  2160.         }
  2161.       } while (srchstatus == PSEARCH_STATUS_SUCCESS);
  2162.       
  2163.       /* redo highlight item */
  2164.       if (menuptr->highlight > 0)
  2165.       {
  2166.         pset_elem_ptr(0);      
  2167.         find_item(menuptr->menustid, menuptr->highlight, &elptr);
  2168.         pset_elem_ptr(elptr);
  2169.         redrawboxmenuitem(menuptr->httextcolour, 
  2170.                   menuptr->htintcolour, menuptr->htedgecolour, 
  2171.                   menuptr->httlcolour, menuptr->htbrcolour);
  2172.       }
  2173.       ptk_closestruct();
  2174.  
  2175.       /* set text font */
  2176.       ptk_openstruct(menuptr->menustid);
  2177.       pset_elem_ptr(0);
  2178.       pset_elem_ptr_label(ptk_stringtoint("label", "charheight"));
  2179.       poffset_elem_ptr(2);
  2180.       pdel_elem();
  2181.       pset_text_font(font);
  2182.       ptk_closestruct();
  2183.       if (menuptr->longstr[0] != '\0')
  2184.       {
  2185.         pt = ptk_point(menuptr->boxsize.x - 
  2186.                        (2.0 * menuptr->framesize.x), 
  2187.                        menuptr->boxsize.y -
  2188.                        (2.0 * menuptr->framesize.y)); 
  2189.         ptk_computecharheight(menuptr->wsid, menuptr->longstr,  
  2190.                             &pt, menuptr->font, &charheight);
  2191.         if (charheight < menuptr->charheight)
  2192.         {
  2193.           menuptr->charheight = charheight;
  2194.           ptk_openstruct(menuptr->menustid);
  2195.           pset_elem_ptr(0);
  2196.           pset_elem_ptr_label(ptk_stringtoint("label", "charheight"));
  2197.           poffset_elem_ptr(1);
  2198.           pdel_elem();
  2199.           pset_char_ht(charheight);
  2200.           ptk_closestruct();
  2201.         } 
  2202.       }
  2203.       
  2204.       /* set menu path */
  2205.       ptk_openstruct(menuptr->menustid);
  2206.       pset_elem_ptr(0);
  2207.       pset_elem_ptr_label(ptk_stringtoint("label", "begin-menu"));
  2208.  
  2209.       /* replace all local transformations following pick identifiers */
  2210.       elemlist[0] = PELEM_PICK_ID;
  2211.       elemlist[1] = PELEM_LOCAL_MODEL_TRAN3;
  2212.       do
  2213.       {
  2214.         ptk_findelemtype(elemlist, 2, PDIR_FORWARD, &srchstatus, &elptr, &lstnum);
  2215.         if (srchstatus == PSEARCH_STATUS_SUCCESS)
  2216.     {
  2217.           pset_elem_ptr(elptr);
  2218.           switch (lstnum)
  2219.       {
  2220.             case 0: /* PELEM_PICK_ID */
  2221.               pcreate_store(&err, &store);
  2222.               ptk_inqcurelemtypesizecontent(store, &err, &elcont);
  2223.               itemnum = elcont.eldata->int_data;
  2224.               ptk_delstore(store);
  2225.               break;
  2226.  
  2227.             case 1: /* PELEM_LOCAL_MODEL_TRAN3 */
  2228.               if (itemnum > 0)
  2229.           {
  2230.                 tlpt = get_tlboxcorner(itemnum);
  2231.                 ptk_shift3(&tlpt, PTYPE_REPLACE, shiftmat);
  2232.                 ptk_seteditmode(PEDIT_REPLACE);
  2233.                 pset_local_tran3(shiftmat, PTYPE_REPLACE); 
  2234.                 ptk_unseteditmode();
  2235.                 itemnum = 0;
  2236.               }
  2237.               break;
  2238.           }
  2239.           poffset_elem_ptr(1);
  2240.         }
  2241.       } while (srchstatus == PSEARCH_STATUS_SUCCESS);      
  2242.       ptk_closestruct();
  2243.     }
  2244.   }
  2245. }  /* ptk_setboxmenuattrs */
  2246.  
  2247. /*--------------------------------------------------------------------------*/
  2248.  
  2249. /*function:external*/
  2250. extern void ptk_setboxmenuhighlightitem(C(Pint) menuid, C(Pint) itemnum)
  2251. PreANSI(Pint menuid)
  2252. PreANSI(Pint itemnum)
  2253. /*
  2254. ** \parambegin
  2255. ** \param{Pint}{menuid}{menu identifier}{IN}
  2256. ** \param{Pint}{itemnum}{menu item number}{IN}
  2257. ** \paramend
  2258. ** \blurb{This function highlights a menu item by setting the colour
  2259. ** index values for the text, interior and edge of a box menu item.}
  2260. */
  2261. {
  2262.   Pint elptr;
  2263.  
  2264.   setmenu(menuid);
  2265.   if (menuptr != NULL)
  2266.   {
  2267.     if (menuptr->menutype == PTKEBOXMENU)
  2268.     {
  2269.       ptk_openstruct(menuptr->menustid);
  2270.       ptk_seteditmode(PEDIT_INSERT);
  2271.       pset_elem_ptr(0);
  2272.       if (itemnum != menuptr->highlight)
  2273.       {
  2274.         /* redraw previously highlighted item in normal colours*/
  2275.         if (menuptr->highlight > 0)
  2276.         {
  2277.           /* redraw item */
  2278.           find_item(menuptr->menustid, menuptr->highlight, &elptr);
  2279.           pset_elem_ptr(elptr);
  2280.           redrawboxmenuitem(menuptr->textcolour, 
  2281.                   menuptr->intcolour, menuptr->edgecolour, 
  2282.                   menuptr->tlcolour, menuptr->brcolour);
  2283.         }
  2284.         /* redraw item in highlight colours */
  2285.         find_item(menuptr->menustid, itemnum, &elptr);
  2286.         pset_elem_ptr(elptr);
  2287.         redrawboxmenuitem(menuptr->httextcolour, 
  2288.                menuptr->htintcolour, menuptr->htedgecolour, 
  2289.                menuptr->httlcolour, menuptr->htbrcolour);
  2290.       }
  2291.       ptk_unseteditmode();
  2292.       ptk_closestruct();
  2293.       menuptr->highlight = itemnum;
  2294.     }
  2295.   }
  2296. }  /* ptk_setboxmenuhighlightitem */
  2297.  
  2298. /*--------------------------------------------------------------------------*/
  2299.  
  2300. /*function:external*/
  2301. extern void ptk_clearboxmenuhighlight(C(Pint) menuid)
  2302. PreANSI(Pint menuid)
  2303. /*
  2304. ** \parambegin
  2305. ** \param{Pint}{menuid}{menu identifier}{IN}
  2306. ** \paramend
  2307. ** \blurb{This function returns the attributes of the highlighted menu item
  2308. ** to their original values. If no item is highlighted the function is
  2309. ** ignored.}
  2310. */
  2311. {
  2312.   Pint elptr;
  2313.  
  2314.   setmenu(menuid);
  2315.   if (menuptr != NULL)
  2316.   {
  2317.     if (menuptr->highlight > 0)
  2318.     {
  2319.       ptk_openstruct(menuptr->menustid);
  2320.       ptk_seteditmode(PEDIT_INSERT);
  2321.       pset_elem_ptr(0);
  2322.   
  2323.       find_item(menuptr->menustid, menuptr->highlight, &elptr);
  2324.       pset_elem_ptr(elptr);
  2325.       redrawboxmenuitem(menuptr->textcolour, 
  2326.                   menuptr->intcolour, menuptr->edgecolour, 
  2327.                   menuptr->tlcolour, menuptr->brcolour);
  2328.   
  2329.       ptk_unseteditmode();
  2330.       ptk_closestruct();
  2331.       menuptr->highlight = 0;
  2332.     }
  2333.   }
  2334. }  /* ptk_clearboxmenuhighlight */
  2335.  
  2336. /*--------------------------------------------------------------------------*/
  2337.  
  2338. /*function:external*/
  2339. extern void ptk_inqpostedmenus(C(Pint) wsid, C(Pint) size, 
  2340.         C(Pint_list *) menuids, C(Pint *) totalsize, C(Pint *) err)
  2341. PreANSI(Pint wsid)
  2342. PreANSI(Pint size)
  2343. PreANSI(Pint_list *menuids)
  2344. PreANSI(Pint *totalsize)
  2345. PreANSI(Pint *err)
  2346. /*
  2347. ** \parambegin
  2348. ** \param{Pint}{wsid}{workstation identifier}{IN}
  2349. ** \param{Pint}{size}{size of buffer}{IN}
  2350. ** \param{Pint\_list *}{menuids}{list of posted menus}{OUT}
  2351. ** \param{Pint *}{totalsize}{length of posted menus list}{OUT}
  2352. ** \param{Pint *}{err}{error indicator}{OUT}
  2353. ** \paramend
  2354. ** \blurb{This function may be used to inquire the list of all menus
  2355. ** which are posted to workstation {\tt wsid}. The error code is
  2356. ** a standard PHIGS error code.}
  2357. */
  2358. {
  2359.   ptksmenu *ptrmenu;
  2360.   Pint numstructs, i;
  2361.   Pposted_struct_list structlist;
  2362.  
  2363.   *err = 0;
  2364.   *totalsize = 0;
  2365.   ptrmenu = firstmenu;
  2366.   while (ptrmenu != NULL)
  2367.   {
  2368.     if ((inintlst(wsid, &ptrmenu->posted) != -1))
  2369.       (*totalsize)++;
  2370.     ptrmenu = ptrmenu->next;
  2371.   }
  2372.   if (size >= *totalsize)
  2373.   {
  2374.     pinq_posted_structs(wsid, 0, 0, err, &structlist, &numstructs);
  2375.     structlist.postings = (Pposted_struct *)calloc(numstructs, 
  2376.                                               sizeof(Pposted_struct));
  2377.     pinq_posted_structs(wsid, numstructs, 0, err, &structlist, &numstructs);
  2378.     menuids->num_ints = 0;
  2379.     for (i = 0; i < structlist.num_postings; i++)
  2380.     {
  2381.       if (ismenu(structlist.postings[i].id, &ptrmenu))
  2382.       {
  2383.         menuids->ints[menuids->num_ints] = ptrmenu->menuid;
  2384.         menuids->num_ints++;
  2385.       }
  2386.     }
  2387.   }
  2388. }  /* ptk_inqpostedmenus */
  2389.  
  2390. /*--------------------------------------------------------------------------*/
  2391.  
  2392. /*function:external*/
  2393. extern void ptk_inqmenuids(C(Pint) size, C(Pint_list *) menuids, 
  2394.                            C(Pint *) totalsize, C(Pint *) err)
  2395. PreANSI(Pint size)
  2396. PreANSI(Pint_list *menuids)
  2397. PreANSI(Pint *totalsize)
  2398. PreANSI(Pint *err)
  2399. /*
  2400. ** \parambegin
  2401. ** \param{Pint}{size}{size of buffer}{IN}
  2402. ** \param{Pint\_list *}{menuids}{list of menus}{OUT}
  2403. ** \param{Pint *}{totalsize}{length of menus list}{OUT}
  2404. ** \param{Pint *}{err}{error indicator}{OUT}
  2405. ** \paramend
  2406. ** \blurb{This function may be used to obtain a list of all menus
  2407. ** in the PHIGS Toolkit menu store.}
  2408. */
  2409. {
  2410.   ptksmenu *ptrmenu;
  2411.  
  2412.   *err = 0;
  2413.   *totalsize = menucount;
  2414.   if (size >= *totalsize)
  2415.   {
  2416.     menuids->num_ints = 0;
  2417.     ptrmenu = firstmenu;
  2418.     while (ptrmenu != NULL)
  2419.     {
  2420.       menuids->ints[menuids->num_ints] = ptrmenu->menuid;
  2421.       menuids->num_ints++;
  2422.       ptrmenu = ptrmenu->next;
  2423.     }
  2424.   }
  2425. }  /* ptk_inqmenuids */
  2426.  
  2427. /*--------------------------------------------------------------------------*/
  2428.  
  2429. /*function:external*/
  2430. extern void ptk_inqmenustructid(C(Pint) menuid, C(Pint *) menustid, 
  2431.                                 C(Pint *) err)
  2432. PreANSI(Pint menuid)
  2433. PreANSI(Pint *menustid)
  2434. PreANSI(Pint *err)
  2435. /*
  2436. ** \parambegin
  2437. ** \param{Pint}{menuid}{menu identifier}{IN}
  2438. ** \param{Pint *}{menustid}{menu structure identifier}{OUT}
  2439. ** \param{Pint *}{err}{error indicator}{OUT}
  2440. ** \paramend
  2441. ** \blurb{This function may be used to obtain the identifier
  2442. ** of a menu structure. The error code = 1 if {\tt menuid} doesn't exist.}
  2443. */
  2444. {
  2445.   *err = 0;
  2446.   setmenu(menuid);
  2447.   if (menuptr != NULL)
  2448.     *menustid = menuptr->menustid;
  2449.   else
  2450.     *err = 1;
  2451. }  /* ptk_inqmenustructid */
  2452.  
  2453. /*--------------------------------------------------------------------------*/
  2454.  
  2455. /*function:external*/
  2456. extern void ptk_inqmenuname(C(Pint) menuid, C(Pint *) name, 
  2457.                             C(Pint *) err) 
  2458. PreANSI(Pint menuid)
  2459. PreANSI(Pint *name)
  2460. PreANSI(Pint *err)
  2461. /*
  2462. ** \parambegin
  2463. ** \param{Pint}{windid}{menu identifier}{IN}
  2464. ** \param{Pint *}{name}{menu name}{OUT}
  2465. ** \param{Pint *}{err}{error indicator}{OUT}
  2466. ** \paramend
  2467. ** \blurb{This function may be used to obtain the menu name 
  2468. ** for use in the pick filter.
  2469. ** The error code = 1 if {\tt menuid} doesn't exist.}
  2470. */
  2471. {
  2472.   *err = 0;
  2473.   setmenu(menuid);
  2474.   if (menuptr != NULL)
  2475.     *name = menuptr->menuname;
  2476.   else
  2477.     *err = 1;
  2478. }  /* ptk_inqmenuname */
  2479.  
  2480. /*--------------------------------------------------------------------------*/
  2481.  
  2482. /*function:external*/
  2483. extern ptkboolean ptk_inqfrontbackmenuid(C(Pint) wsid, C(Pint *) frontid, 
  2484.                                       C(Pint *) backid, C(Pint *) err)
  2485. PreANSI(Pint wsid)
  2486. PreANSI(Pint *frontid)
  2487. PreANSI(Pint *backid)
  2488. PreANSI(Pint *err)
  2489. /*
  2490. ** \parambegin
  2491. ** \param{Pint}{wsid}{workstation identifier}{IN}
  2492. ** \param{Pint *}{frontstid}{front menu identifier}{OUT}
  2493. ** \param{Pint *}{backstid}{back menu identifier}{OUT}
  2494. ** \param{Pint *}{err}{error indicator}{OUT}
  2495. ** \paramend
  2496. ** \blurb{This function may be used to obtain the menu identifiers
  2497. ** of the front and back menus which are posted to workstation {\tt wsid}. 
  2498. ** These are the menus with the highest and lowest post priority.}
  2499. ** 
  2500. */
  2501. {
  2502.   Pint ind;
  2503.  
  2504.   *err = 0;
  2505.   findwsid(wsid, &ind);
  2506.   if (wsmenus[ind].postedmenus)
  2507.   {
  2508.     *frontid = wsmenus[ind].frontptr->menuid;
  2509.     *backid = wsmenus[ind].backptr->menuid;
  2510.     return TRUE;
  2511.   }
  2512.   else
  2513.     return FALSE;
  2514. }  /* ptk_inqfrontbackmenuid */
  2515.  
  2516. /*--------------------------------------------------------------------------*/
  2517.  
  2518. /*function:external*/
  2519. extern void ptk_inqboxmenuattrs(C(Pint) menuid, 
  2520.             C(Ptext_path *) menupath, C(Pint *) font, C(Pint *) textcolour, 
  2521.             C(Pint *) intcolour, C(Pint *) edgecolour, C(Pint *) boxtlcolour, 
  2522.             C(Pint *) boxbrcolour, C(Pint *) httextcolour, 
  2523.             C(Pint *) htintcolour, C(Pint *) htedgecolour, C(Pint *) err)
  2524. PreANSI(Pint menuid)
  2525. PreANSI(Ptext_path *menupath)
  2526. PreANSI(Pint *font)
  2527. PreANSI(Pint *textcolour)
  2528. PreANSI(Pint *intcolour)
  2529. PreANSI(Pint *edgecolour)
  2530. PreANSI(Pint *boxtlcolour)
  2531. PreANSI(Pint *boxbrcolour)
  2532. PreANSI(Pint *httextcolour)
  2533. PreANSI(Pint *htintcolour)
  2534. PreANSI(Pint *htedgecolour) 
  2535. PreANSI(Pint *err)
  2536. /*
  2537. ** \parambegin
  2538. ** \param{Pint}{menuid}{menu identifier}{IN}
  2539. ** \param{Ptext\_path *}{menupath}{path of box menu (left, right, up, down)}{OUT}
  2540. ** \param{Pint *}{font}{text font}{OUT}
  2541. ** \param{Pint *}{textcolour}{colour index for text}{OUT}
  2542. ** \param{Pint *}{intcolour}{colour index for interior}{OUT}
  2543. ** \param{Pint *}{edgecolour}{colour index for edges}{OUT}
  2544. ** \param{Pint *}{boxtlcolour}{colour index for top-left of box}{OUT}
  2545. ** \param{Pint *}{boxcolour}{colour index for bottom-right of box}{OUT}
  2546. ** \param{Pint *}{httextcolour}{colour index for highlight text}{OUT}
  2547. ** \param{Pint *}{htintcolour}{colour index for highlight interior}{OUT}
  2548. ** \param{Pint *}{htedgecolour}{colour index for highlight edges}{OUT}
  2549. ** \param{Pint *}{err}{error indicator}{OUT}
  2550. ** \paramend
  2551. ** \blurb{This function may be used to obtain the boxmenu attribute
  2552. ** values for {\tt menuid}. These include the menu path, text font and
  2553. ** colour indicies. The error code = 1 if {\tt menuid} doesn't exist
  2554. ** and = 2 if it is not a box menu.}
  2555. */
  2556. {
  2557.   *err = 0;
  2558.   setmenu(menuid);
  2559.   if (menuptr != NULL)
  2560.   {
  2561.     if (menuptr->menutype == PTKEBOXMENU)
  2562.     {
  2563.       *menupath = menuptr->menupath;
  2564.       *font = menuptr->font;
  2565.       *textcolour = menuptr->textcolour;
  2566.       *intcolour = menuptr->intcolour;
  2567.       *edgecolour = menuptr->edgecolour;
  2568.       *boxtlcolour = menuptr->tlcolour;
  2569.       *boxbrcolour = menuptr->brcolour;
  2570.       *httextcolour = menuptr->httextcolour;
  2571.       *htintcolour = menuptr->htintcolour;
  2572.       *htedgecolour = menuptr->htedgecolour;
  2573.     }
  2574.     else
  2575.       *err = 2;
  2576.   }
  2577.   else
  2578.     *err = 1;
  2579. }  /* ptk_inqboxmenuattrs */
  2580.  
  2581. /*--------------------------------------------------------------------------*/
  2582.  
  2583. /*function:external*/
  2584. extern void ptk_inqmenuposition(C(Pint) menuid, C(Ppoint *) position, 
  2585.                                 C(Pint *) err)
  2586. PreANSI(Pint menuid)
  2587. PreANSI(Ppoint *position)
  2588. PreANSI(Pint *err)
  2589. /*
  2590. ** \parambegin
  2591. ** \param{Pint}{menuid}{menu identifier}{IN}
  2592. ** \param{Ppoint *}{position}{menu position}{OUT}
  2593. ** \param{Pint *}{err}{error indicator}{OUT}
  2594. ** \paramend
  2595. ** \blurb{This function may be used to obtain the position of the
  2596. ** top-left corner of first menu item. The position is returned in the
  2597. ** range [0, 1]. The error code = 1 if {\tt menuid} doesn't exist.}
  2598. */
  2599. {
  2600.   *err = 0;
  2601.   setmenu(menuid);
  2602.   if (menuptr != NULL)
  2603.     *position = menuptr->menuposition;
  2604.   else
  2605.     *err = 1;
  2606. }  /* ptk_inqmenuposition */
  2607.  
  2608. /*--------------------------------------------------------------------------*/
  2609.  
  2610. /*function:external*/
  2611. extern void ptk_inqboxmenuhighlightitem(C(Pint) menuid, C(Pint *) item, 
  2612.                                 C(Pint *) err)
  2613. PreANSI(Pint menuid)
  2614. PreANSI(Pint *item)
  2615. PreANSI(Pint *err)
  2616. /*
  2617. ** \parambegin
  2618. ** \param{Pint}{menuid}{menu identifier}{IN}
  2619. ** \param{Pint *}{item}{hightlight item number}{OUT}
  2620. ** \param{Pint *}{err}{error indicator}{OUT}
  2621. ** \paramend
  2622. ** \blurb{This function may be used to obtain the item number of the
  2623. ** currently highlight box menu item. 
  2624. ** The error code = 1 if {\tt menuid} doesn't exist and = 2 if there
  2625. ** is no highlighted item.}
  2626. */
  2627. {
  2628.   *err = 0;
  2629.   setmenu(menuid);
  2630.   if (menuptr != NULL)
  2631.   {
  2632.     if (menuptr->highlight > 0)
  2633.       *item = menuptr->highlight;
  2634.     else
  2635.       *err = 2;
  2636.   }
  2637.   else
  2638.     *err = 1;
  2639. }  /* ptk_inqboxmenuhighlightitem */
  2640.  
  2641. /*--------------------------------------------------------------------------*/
  2642. /*------------------- exported rotator routines ----------------------------*/
  2643. /*--------------------------------------------------------------------------*/
  2644.  
  2645. static void createrotator(C(Pint) wsid, C(Pint) menuid,
  2646.             C(ptkerotatortype) rottype, C(Ppoint *) size, 
  2647.             C(char *) titlestr, C(Pfloat) titleheight, C(Pint) titlecolour,
  2648.             C(Pint) titlefont, C(Pint) arrowcolour, C(Pint) arrowedgecolour,
  2649.             C(Pint) intcolour, C(Pint) edgecolour, C(Pint) bannercolour, 
  2650.             C(Pint) boxtlcolour, C(Pint) boxbrcolour)
  2651. PreANSI(Pint wsid)
  2652. PreANSI(Pint menuid)
  2653. PreANSI(ptkerotatortype rottype)
  2654. PreANSI(Ppoint *size)
  2655. PreANSI(char *titlestr)
  2656. PreANSI(Pfloat titleheight)
  2657. PreANSI(Pint titlecolour)
  2658. PreANSI(Pint titlefont)
  2659. PreANSI(Pint arrowcolour)
  2660. PreANSI(Pint arrowedgecolour)
  2661. PreANSI(Pint intcolour)
  2662. PreANSI(Pint edgecolour)
  2663. PreANSI(Pint bannercolour)
  2664. PreANSI(Pint boxtlcolour)
  2665. PreANSI(Pint boxbrcolour)
  2666. /*
  2667. ** \parambegin
  2668. ** \param{Pint}{wsid}{workstation identifier}{IN}
  2669. ** \param{Pint}{menuid}{rotator identifier}{IN}
  2670. ** \param{ptkerotatortype}{rottype}{rotator type}{IN}
  2671. ** \param{Ppoint *}{size}{rotator size}{IN}
  2672. ** \param{char *}{titlestr}{rotator title}{IN}
  2673. ** \param{Pfloat}{titleheight}{rotator title height}{IN}
  2674. ** \param{Pint}{titlecolour}{title colour index}{IN}
  2675. ** \param{Pint}{titlefont}{title font}{IN}
  2676. ** \param{Pint}{arrowcolour}{arrow interior colour index}{IN}
  2677. ** \param{Pint}{arrowedgecolour}{arrow edge colour index}{IN}
  2678. ** \param{Pint}{intcolour}{rotator interior colour index}{IN}
  2679. ** \param{Pint}{edgecolour}{edge colour index}{IN}
  2680. ** \param{Pint}{bannercolour}{banner colour index}{IN}
  2681. ** \param{Pint}{boxtlcolour}{top-left colour index}{IN}
  2682. ** \param{Pint}{boxbrcolour}{bottom-right colour index}{IN}
  2683. ** \paramend
  2684. ** \blurb{Create rotator with given specification.}
  2685. */
  2686. {
  2687.   Pmatrix3 matrix, mat, boxmat;
  2688.   char stname[30], str[10];
  2689.   Pint arrowid, menustid, elptr, pickval, err;
  2690.   Pfloat charheight;
  2691.   Plimit3 ubox, rbox;
  2692.   Ppoint3 arrowcentre, centre;
  2693.   Ppoint3 arrowshift, arrowscale, boxscale, boxpos;
  2694.   Ppoint_list sets;
  2695.   Ppoint pts[4], centresize, framesize, shift, scale, textpos;
  2696.   Ppoint boxsize, iconbox;
  2697.   Ptext_align txalign;
  2698.   Pint_list incl;
  2699.   
  2700.   setmenu(menuid);
  2701.   if (menuptr == NULL)
  2702.   {
  2703.     sprintf(stname, "ptk$menu%d", menuid);
  2704.     menustid = ptk_stringtoint("structureid", stname);
  2705.     ptk_createusermenu(menuid, menustid);
  2706.     setmenu(menuid);
  2707.     ptk_openstruct(menustid);
  2708.     ptk_seteditmode(PEDIT_INSERT);
  2709.     pset_elem_ptr(0);
  2710.     pset_elem_ptr_label(ptk_stringtoint("label", "begin-menu"));
  2711.     poffset_elem_ptr(-2);
  2712.   
  2713.     /* rotator surrounds */
  2714.     menuptr->wsid = wsid;
  2715.     menuptr->font = titlefont;
  2716.     menuptr->menutype = PTKEROTATOR;
  2717.     menuptr->intcolour = intcolour;
  2718.     menuptr->edgecolour = edgecolour;
  2719.     menuptr->tlcolour = boxtlcolour;
  2720.     menuptr->brcolour = boxbrcolour;
  2721.     menuptr->textcolour = titlecolour;
  2722.     menuptr->arrowcolour = arrowcolour;
  2723.     menuptr->arrowedgecolour = arrowedgecolour;
  2724.     menuptr->bannercolour = bannercolour;
  2725.     menuptr->boxsize = *size;
  2726.     menuptr->boxsize.y += titleheight;
  2727.     menuptr->framesize = ptk_point(0.01, 0.01); 
  2728.     strcpy(menuptr->longstr, titlestr);
  2729.     
  2730.     centre = ptk_point3(0.0, titleheight / 2.0, 0.0);
  2731.     centresize = *size;
  2732.     centresize.y += titleheight;
  2733.     centresize.x -= menuptr->framesize.x * 2.0;
  2734.     centresize.y -= menuptr->framesize.y * 2.0;
  2735.  
  2736.     ptk_framebox(¢re, ¢resize, &menuptr->framesize,
  2737.                  intcolour, edgecolour, boxtlcolour, boxbrcolour);
  2738.     pts[0] = ptk_point(-centresize.x / 2.0, centresize.y / 2.0 - 
  2739.                        titleheight / 2.0);
  2740.     pts[1] = ptk_point(pts[0].x, pts[0].y + titleheight);
  2741.     pts[2] = ptk_point(pts[0].x + centresize.x, pts[1].y);
  2742.     pts[3] = ptk_point(pts[2].x, pts[0].y);
  2743.  
  2744.     poffset_elem_ptr(1); /* make title pickable */
  2745.     sets.num_points = 4;
  2746.     sets.points = pts;
  2747.     pset_int_colr_ind(bannercolour);
  2748.     ptk_fillareaset(1, &sets);
  2749.     /* Implementation dependent bit - because HP doesn't support
  2750.     ** INQUIRE TEXT EXTENT, kludge to size text in rotator banner.
  2751.     */
  2752. #ifdef SUN
  2753.     menuptr->bannerbox = ptk_point(centresize.x, titleheight);
  2754. #endif
  2755. #ifdef HP
  2756.     menuptr->bannerbox = ptk_point(centresize.x, titleheight * 0.7);
  2757. #endif
  2758. #ifdef PEXSI
  2759.     menuptr->bannerbox = ptk_point(centresize.x, titleheight * 0.7);
  2760. #endif
  2761.     txalign.hor = PHOR_CTR;
  2762.     txalign.vert = PVERT_BOTTOM;
  2763.     pset_text_align(&txalign);
  2764.     pset_text_font(menuptr->font);
  2765.     pset_text_colr_ind(titlecolour);
  2766.     plabel(ptk_stringtoint("label", "rotator$title"));
  2767.     ptk_computecharheight(wsid, titlestr, &menuptr->bannerbox, menuptr->font, 
  2768.                           &charheight);
  2769.     pset_char_ht(charheight);
  2770.     menuptr->bannercentre = ptk_point(centre.x, centresize.y / 2.0 - 
  2771.                              titleheight / 2.0);
  2772.     ptext(&menuptr->bannercentre, titlestr); 
  2773.   
  2774.     /* arrows */
  2775.     pset_int_colr_ind(arrowcolour);
  2776.     pset_edge_colr_ind(arrowedgecolour);
  2777.   
  2778.     ptk_closestruct();
  2779.   
  2780.     arrowid = ptk_stringtoint("structureid", "ptk$arrow");
  2781.     /* create arrow structure which will be executed by 1d, 2d and 3d 
  2782.     ** rotators.
  2783.     */
  2784.     if (!ptk_structexists(arrowid)) 
  2785.     {
  2786.       ptk_openstruct(arrowid);
  2787.       arrowcentre = ptk_point3(0.0, 0.0, 0.0);
  2788.       ptk_arrow(1.0, 1.0, &arrowcentre, 0.0);     
  2789.       ptk_closestruct();
  2790.     }
  2791.   
  2792.     switch (rottype) 
  2793.     {
  2794.   
  2795.     case PTKEONED:
  2796.       {
  2797.         Ppoint box1d, arrowsize, arrowspace;
  2798.  
  2799.         /* calculate 1d bounding box */
  2800.         box1d.x = box1d.y = PTKMIN(centresize.x, centresize.y);
  2801.   
  2802.         /* calculate arrow size and spacing */
  2803.         arrowsize.x = arrowsize.y = box1d.x / 3.0;
  2804.         arrowspace.x = arrowspace.y = arrowsize.x / 3.0;
  2805.  
  2806.         /* create arrow menu items */
  2807.         ptk_createstructmenuitem(menuid, arrowid, 1, PEDIT_INSERT, &err);
  2808.         ptk_createstructmenuitem(menuid, arrowid, 2, PEDIT_INSERT, &err);
  2809.   
  2810.         /* put in transformations for arrows */
  2811.         boxscale = ptk_point3(arrowsize.x, arrowsize.y, 1.0);
  2812.         ptk_scale3(&boxscale, PTYPE_REPLACE, boxmat);
  2813.  
  2814.         ptk_openstruct(menustid);
  2815.         pset_elem_ptr(0);
  2816.         find_insertion_pt(menustid, 1, &elptr, &pickval);
  2817.         pset_elem_ptr(elptr);
  2818.         ptk_unitmatrix3(mat);
  2819.  
  2820.         /* up arrow */
  2821.         arrowshift = ptk_point3(0.0, 
  2822.                           arrowspace.y + (arrowsize.y / 2.0), 0.0);
  2823.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2824.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);   
  2825.         pset_local_tran3(mat, PTYPE_REPLACE);
  2826.   
  2827.         /* down arrow */
  2828.         arrowshift = ptk_point3(0.0, 
  2829.                         -(arrowspace.y + (arrowsize.y / 2.0)), 0.0);
  2830.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2831.         arrowscale = ptk_point3(1.0, -1.0, 1.0);
  2832.         ptk_scale3(&arrowscale, PTYPE_PRECONCAT, mat);
  2833.         /* jump to just before next execute element */
  2834.         poffset_elem_ptr(2);    
  2835.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2836.         pset_local_tran3(mat, PTYPE_REPLACE);
  2837.   
  2838.         ptk_closestruct();
  2839.       }
  2840.       break;
  2841.  
  2842.     case PTKETWOD:
  2843.       {
  2844.         Ppoint box2d, arrowsize, arrowspace;
  2845.  
  2846.         /* calculate 2d bounding box */
  2847.         box2d.x = box2d.y = PTKMIN(centresize.x, centresize.y);
  2848.   
  2849.         /* calculate arrow size and spacing */
  2850.         arrowsize.x = arrowsize.y = box2d.x / 3.0;
  2851.         arrowspace.x = arrowspace.y = arrowsize.x / 3.0;
  2852.   
  2853.         /* create arrow menu items */
  2854.         ptk_createstructmenuitem(menuid, arrowid, 1, PEDIT_INSERT, &err);
  2855.         ptk_createstructmenuitem(menuid, arrowid, 2, PEDIT_INSERT, &err);
  2856.         ptk_createstructmenuitem(menuid, arrowid, 3, PEDIT_INSERT, &err);
  2857.         ptk_createstructmenuitem(menuid, arrowid, 4, PEDIT_INSERT, &err);
  2858.   
  2859.         /* put in transformations for arrows */
  2860.         boxscale = ptk_point3(arrowsize.x, arrowsize.y, 1.0);
  2861.         ptk_scale3(&boxscale, PTYPE_REPLACE, boxmat);
  2862.  
  2863.         ptk_openstruct(menustid);
  2864.         pset_elem_ptr(0);
  2865.         find_insertion_pt(menustid, 1, &elptr, &pickval);
  2866.         pset_elem_ptr(elptr);
  2867.         ptk_unitmatrix3(mat);
  2868.         arrowshift = ptk_point3(0.0, 
  2869.                           arrowspace.y + (arrowsize.y / 2.0), 0.0);
  2870.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2871.         /* m is a shift by (0.0, arrowsep) */
  2872.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2873.         pset_local_tran3(mat, PTYPE_REPLACE);
  2874.   
  2875.         arrowshift = ptk_point3(0.0, 
  2876.                         -(arrowspace.y + (arrowsize.y / 2.0)), 0.0);
  2877.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2878.         arrowscale = ptk_point3(1.0, -1.0, 1.0);
  2879.         ptk_scale3(&arrowscale, PTYPE_PRECONCAT, mat);
  2880.         /* jump to just before next execute element */
  2881.         poffset_elem_ptr(2);    
  2882.         /* m is now a reflection in the x axis. */
  2883.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2884.         pset_local_tran3(mat, PTYPE_REPLACE);
  2885.     
  2886.         poffset_elem_ptr(2);
  2887.         /* add shift component to matrix to shift by (0, arrowsep, 0) */
  2888.  
  2889.         arrowshift = ptk_point3(0.0, 
  2890.                         (arrowspace.x + (arrowsize.x / 2.0)), 0.0);
  2891.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2892.         ptk_rotate3(90.0, PTKEZAXIS, PTYPE_POSTCONCAT, mat);
  2893.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2894.         pset_local_tran3(mat, PTYPE_REPLACE);
  2895.     
  2896.         /* +x is a reflection of -x in the y axis */
  2897.         arrowscale = ptk_point3(-1.0, 1.0, 1.0);
  2898.         ptk_scale3(&arrowscale, PTYPE_POSTCONCAT, mat);
  2899.         poffset_elem_ptr(2);
  2900.         pset_local_tran3(mat, PTYPE_REPLACE);
  2901.   
  2902.         ptk_closestruct();
  2903.       }
  2904.       break;
  2905.   
  2906.     case PTKETHREED:
  2907.       {
  2908.         Ppoint box3d, arrowsize, arrowspace;
  2909.         Pfloat aspectratio, aspectratio3d, diff;
  2910.  
  2911.         /* calculate 3d bounding box */
  2912.         box3d = centresize;
  2913.         /* calculate aspect ratio of box */
  2914.         aspectratio = centresize.y / centresize.x;
  2915.         aspectratio3d = 2.0 / 3.0;      
  2916.         if (aspectratio < aspectratio3d)
  2917.         {
  2918.           /* decrease x */
  2919.           diff = (centresize.x - ((1.0 / aspectratio3d) * centresize.y));
  2920.           box3d.x -= diff;
  2921.         }
  2922.         else
  2923.         if (aspectratio > aspectratio3d)
  2924.         {
  2925.           /* decrease y */
  2926.           diff = (centresize.y - (aspectratio3d * centresize.x));
  2927.           box3d.y -= diff;
  2928.         }       
  2929.  
  2930.         /* calculate arrow size and spacing */
  2931.         arrowsize.x = arrowsize.y = (box3d.x / 17.0) * 3.0;
  2932.         arrowspace = ptk_point(arrowsize.x / 3.0, arrowsize.y / 3.0);
  2933.   
  2934.         /* create arrow menu items */
  2935.         ptk_createstructmenuitem(menuid, arrowid, 1, PEDIT_INSERT, &err);
  2936.         ptk_createstructmenuitem(menuid, arrowid, 2, PEDIT_INSERT, &err);
  2937.         ptk_createstructmenuitem(menuid, arrowid, 3, PEDIT_INSERT, &err);
  2938.         ptk_createstructmenuitem(menuid, arrowid, 4, PEDIT_INSERT, &err);
  2939.         ptk_createstructmenuitem(menuid, arrowid, 5, PEDIT_INSERT, &err);
  2940.         ptk_createstructmenuitem(menuid, arrowid, 6, PEDIT_INSERT, &err);
  2941.  
  2942.         /* put in transformations for arrows */
  2943.         boxscale = ptk_point3(arrowsize.x, arrowsize.y, 1.0);
  2944.         ptk_scale3(&boxscale, PTYPE_REPLACE, boxmat);
  2945.   
  2946.         ptk_openstruct(menustid);
  2947.         pset_elem_ptr(0);
  2948.         find_insertion_pt(menustid, 1, &elptr, &pickval);
  2949.         pset_elem_ptr(elptr);
  2950.         ptk_unitmatrix3(mat);
  2951.  
  2952.         arrowshift = ptk_point3(0.0, 
  2953.                           arrowspace.y + (arrowsize.y / 2.0), 0.0);
  2954.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2955.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2956.         pset_local_tran3(mat, PTYPE_REPLACE);
  2957.   
  2958.         arrowshift = ptk_point3(0.0, 
  2959.                         -(arrowspace.y + (arrowsize.y / 2.0)), 0.0);
  2960.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2961.         arrowscale = ptk_point3(1.0, -1.0, 1.0);
  2962.         ptk_scale3(&arrowscale, PTYPE_PRECONCAT, mat);
  2963.         /* jump to just before next execute element */
  2964.         poffset_elem_ptr(2);    
  2965.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2966.         pset_local_tran3(mat, PTYPE_REPLACE);
  2967.     
  2968.         poffset_elem_ptr(2);
  2969.         arrowshift = ptk_point3(0.0, 
  2970.                         (arrowspace.y + (arrowsize.y / 2.0)), 0.0);
  2971.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2972.         ptk_rotate3(90.0, PTKEZAXIS, PTYPE_POSTCONCAT, mat);
  2973.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2974.         pset_local_tran3(mat, PTYPE_REPLACE);
  2975.     
  2976.         arrowscale = ptk_point3(-1.0, 1.0, 1.0);
  2977.         ptk_scale3(&arrowscale, PTYPE_POSTCONCAT, mat);
  2978.         poffset_elem_ptr(2);
  2979.         pset_local_tran3(mat, PTYPE_REPLACE);
  2980.     
  2981.         poffset_elem_ptr(2);
  2982.         arrowshift = ptk_point3((arrowspace.y * 3.0) / 2.0 + arrowsize.y + 
  2983.                                 (arrowsize.x / 2.0), 0.0, 0.0);
  2984.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2985.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2986.         pset_local_tran3(mat, PTYPE_REPLACE);
  2987.     
  2988.         poffset_elem_ptr(2);
  2989.         arrowshift = ptk_point3(-((arrowspace.y * 3.0) / 2.0 + arrowsize.y + 
  2990.                                 (arrowsize.x / 2.0)), 0.0, 0.0);
  2991.         ptk_shift3(&arrowshift, PTYPE_REPLACE, mat);
  2992.         ptk_concatenatematrix3(PTYPE_PRECONCAT, boxmat, mat, mat);
  2993.         pset_local_tran3(mat, PTYPE_REPLACE);
  2994.         ptk_closestruct();
  2995.       }
  2996.       break;
  2997.     }
  2998.     ptk_unseteditmode();
  2999.   }
  3000. }  /* createrotator */
  3001.  
  3002. /*--------------------------------------------------------------------------*/
  3003.  
  3004. /*function:external*/
  3005. extern void ptk_createrotator(C(Pint) wsid, C(Pint) menuid,
  3006.             C(ptkerotatortype) rottype, C(Ppoint *) size, 
  3007.             C(char *) titlestr, C(Pfloat) titleheight)
  3008. PreANSI(Pint wsid)
  3009. PreANSI(Pint menuid)
  3010. PreANSI(ptkerotatortype rottype)
  3011. PreANSI(Ppoint *size)
  3012. PreANSI(char *titlestr)
  3013. PreANSI(Pfloat titleheight)
  3014. /*
  3015. ** \parambegin
  3016. ** \param{Pint}{wsid}{workstation identifier}{IN}
  3017. ** \param{Pint}{menuid}{rotator identifier}{IN}
  3018. ** \param{ptkerotatortype}{rottype}{rotator type}{IN}
  3019. ** \param{Ppoint *}{size}{rotator size}{IN}
  3020. ** \param{char *}{titlestr}{rotator title}{IN}
  3021. ** \param{Pfloat}{titleheight}{rotator title height}{IN}
  3022. ** \paramend
  3023. ** \blurb{This function creates a special form of user menu called a
  3024. ** rotator. Rotators consist of an arrangement of arrows and are useful
  3025. ** for defining rotation values and direction in a user interface.
  3026. ** There are three types of rotator available: 1D, 2D and 3D, and each
  3027. ** having an increasing number of arrows.
  3028. ** This function requires hashtables "structureid", "label", "name".} 
  3029. */
  3030. {
  3031.   createrotator(wsid, menuid, rottype, size, titlestr, titleheight,
  3032.                 0, 1, 0, 1, 0, 0, 1, 1, 1);
  3033. }  /* ptk_createrotator */
  3034.  
  3035. /*--------------------------------------------------------------------------*/
  3036.  
  3037. /*function:external*/
  3038. extern void ptk_setrotatortitle(C(Pint) menuid, C(char *) titlestr)
  3039. PreANSI(Pint menuid)
  3040. PreANSI(char *titlestr)
  3041. /*
  3042. ** \parambegin
  3043. ** \param{Pint}{menuid}{menu identifier}{IN}
  3044. ** \param{char *}{titlestr}{title string of rotator banner}{IN}
  3045. ** \paramend 
  3046. ** \blurb{This function sets the title string of the rotator menu
  3047. ** to be {\tt titlestr}. The string is automatically scaled to fit
  3048. ** in the rotator title box.}
  3049. */
  3050. {
  3051.   Pfloat charheight;
  3052.   Pint totlen;
  3053.   
  3054.   setmenu(menuid);
  3055.   if (menuptr != NULL)
  3056.   {  
  3057.     if (menuptr->menutype = PTKEROTATOR)
  3058.     {
  3059.       ptk_openstruct(menuptr->menustid);
  3060.       pset_elem_ptr(0);
  3061.       pset_elem_ptr_label(ptk_stringtoint("label", "rotator$title"));
  3062.       poffset_elem_ptr(1);
  3063.       ptk_seteditmode(PEDIT_REPLACE);
  3064.       ptk_computecharheight(menuptr->wsid, titlestr, &menuptr->bannerbox, 
  3065.                             menuptr->font, &charheight);
  3066.       pset_char_ht(charheight);
  3067.       poffset_elem_ptr(1);
  3068.       ptext(&menuptr->bannercentre, titlestr); 
  3069.       ptk_unseteditmode();
  3070.       ptk_closestruct();
  3071.       totlen = strlen(titlestr) + 1;
  3072.       strncpy(menuptr->longstr, titlestr, totlen);
  3073.     }
  3074.   }
  3075. }  /* ptk_setrotatortitle */
  3076.  
  3077. /*--------------------------------------------------------------------------*/
  3078.  
  3079. /*function:external*/
  3080. extern void ptk_setrotatorattrs(C(Pint) wsid, C(Pint) menuid, 
  3081.            C(Pint) titlefont, C(Pint) titlecolour, 
  3082.            C(Pint) arrowcolour, C(Pint) arrowedgecolour,
  3083.            C(Pint) intcolour, C(Pint) edgecolour, C(Pint) bannercolour, 
  3084.            C(Pint) boxtlcolour, C(Pint) boxbrcolour)
  3085. PreANSI(Pint wsid)
  3086. PreANSI(Pint menuid)
  3087. PreANSI(Pint titlefont)
  3088. PreANSI(Pint titlecolour)
  3089. PreANSI(Pint arrowcolour)
  3090. PreANSI(Pint arrowedgecolour)
  3091. PreANSI(Pint intcolour)
  3092. PreANSI(Pint edgecolour)
  3093. PreANSI(Pint bannercolour)
  3094. PreANSI(Pint boxtlcolour)
  3095. PreANSI(Pint boxbrcolour)
  3096. /*
  3097. ** \parambegin
  3098. ** \param{Pint}{wsid}{workstation identifier}{IN}
  3099. ** \param{Pint}{menuid}{rotator identifier}{IN}
  3100. ** \param{Pint}{titlefont}{title font}{IN}
  3101. ** \param{Pint}{titlecolour}{title colour index}{IN}
  3102. ** \param{Pint}{arrowcolour}{arrow interior colour index}{IN}
  3103. ** \param{Pint}{arrowedgecolour}{arrow edge colour index}{IN}
  3104. ** \param{Pint}{intcolour}{rotator interior colour index}{IN}
  3105. ** \param{Pint}{edgecolour}{edge colour index}{IN}
  3106. ** \param{Pint}{bannercolour}{banner colour index}{IN}
  3107. ** \param{Pint}{boxtlcolour}{top-left colour index}{IN}
  3108. ** \param{Pint}{boxbrcolour}{bottom-right colour index}{IN}
  3109. ** \paramend
  3110. ** \blurb{This function sets the attribute values of a rotator menu.
  3111. ** The arrows are drawn within a box similar to that of box menu
  3112. ** items and the box has an area for a title string. All arrows
  3113. ** are drawn with the same colour values defined by {\tt arrowcolour}
  3114. ** for the interior and {\tt arrowedgecolour} for the outline.}
  3115. */
  3116. {
  3117.   Pfloat charheight;
  3118.   Pint elptr, lstnum, intstate, edgestate;
  3119.   Pelem_type elemlist[3];
  3120.   Psearch_status srchstatus;
  3121.  
  3122.   setmenu(menuid);
  3123.   if (menuptr != NULL)
  3124.   {  
  3125.     if (menuptr->menutype == PTKEROTATOR)
  3126.     {
  3127.       menuptr->wsid = wsid;
  3128.       menuptr->font = titlefont;
  3129.       menuptr->intcolour = intcolour;
  3130.       menuptr->edgecolour = edgecolour;
  3131.       menuptr->tlcolour = boxtlcolour;
  3132.       menuptr->brcolour = boxbrcolour;
  3133.       menuptr->textcolour = titlecolour;
  3134.       menuptr->arrowcolour = arrowcolour;
  3135.       menuptr->arrowedgecolour = arrowedgecolour;
  3136.       menuptr->bannercolour = bannercolour;
  3137.  
  3138.       /* set colours */
  3139.       ptk_openstruct(menuptr->menustid);
  3140.       pset_elem_ptr(0);
  3141.       
  3142.       /* replace all edges, text and interior (in special order) */
  3143.       elemlist[0] = PELEM_EDGE_COLR_IND;
  3144.       elemlist[1] = PELEM_TEXT_COLR_IND;
  3145.       elemlist[2] = PELEM_INT_COLR_IND;
  3146.       intstate = edgestate = 1;
  3147.       do
  3148.       {
  3149.         ptk_findelemtype(elemlist, 3, PDIR_FORWARD, &srchstatus, &elptr, &lstnum);
  3150.         if (srchstatus == PSEARCH_STATUS_SUCCESS)
  3151.     {
  3152.           pset_elem_ptr(elptr);
  3153.           ptk_seteditmode(PEDIT_REPLACE);
  3154.           switch (lstnum)
  3155.       {
  3156.             case 0: /* PELEM_EDGE_COLR_IND */
  3157.               if (edgestate == 1)
  3158.                 pset_edge_colr_ind(edgecolour);
  3159.               else
  3160.                 pset_edge_colr_ind(arrowedgecolour);
  3161.               edgestate++;
  3162.               break;
  3163.  
  3164.             case 1: /* PELEM_TEXT_COLR_IND */
  3165.               pset_text_colr_ind(titlecolour);
  3166.               break;
  3167.  
  3168.             case 2: /* PELEM_INT_COLR_IND */
  3169.               switch (intstate)
  3170.           {
  3171.                 case 1: /* top-left edge */
  3172.                   pset_int_colr_ind(boxtlcolour);
  3173.                   break;
  3174.  
  3175.                 case 2: /* bottom-right edge */
  3176.                   pset_int_colr_ind(boxbrcolour);
  3177.                   break;
  3178.  
  3179.                 case 3: /* box */
  3180.                   pset_int_colr_ind(intcolour);
  3181.                   break;
  3182.  
  3183.                 case 4: /* banner */
  3184.                   pset_int_colr_ind(bannercolour);
  3185.                   break;
  3186.  
  3187.                 case 5: /* arrow */
  3188.                   pset_int_colr_ind(arrowcolour);
  3189.                   break;
  3190.               }
  3191.               intstate++;
  3192.               break;
  3193.           }
  3194.           ptk_unseteditmode();
  3195.           poffset_elem_ptr(1);
  3196.         }
  3197.       } while (srchstatus == PSEARCH_STATUS_SUCCESS);
  3198.       ptk_closestruct();
  3199.  
  3200.       /* set font */
  3201.       ptk_openstruct(menuptr->menustid);
  3202.       ptk_seteditmode(PEDIT_INSERT);
  3203.       pset_elem_ptr(0);
  3204.       pset_elem_ptr_label(ptk_stringtoint("label", "rotator$title"));
  3205.       poffset_elem_ptr(-2);
  3206.       pdel_elem();
  3207.       pset_text_font(titlefont);
  3208.  
  3209.       if (menuptr->longstr[0] != '\0')
  3210.       {
  3211.         ptk_computecharheight(wsid, menuptr->longstr,  
  3212.                             &menuptr->bannerbox, titlefont, &charheight);
  3213.         poffset_elem_ptr(3);
  3214.         pdel_elem();
  3215.         pset_char_ht(charheight);
  3216.       }
  3217.       ptk_unseteditmode();
  3218.       ptk_closestruct();
  3219.     }
  3220.   }
  3221. }  /* ptk_setrotatorattrs */
  3222.  
  3223. /*--------------------------------------------------------------------------*/
  3224.  
  3225. /*function:external*/
  3226. extern void ptk_inqrotatortitle(C(Pint) menuid, C(Pint) len,
  3227.                     C(char *) titlestr, C(Pint *) totlen, C(Pint *) err)
  3228. PreANSI(Pint menuid)
  3229. PreANSI(Pint len)
  3230. PreANSI(char *titlestr)
  3231. PreANSI(Pint *totlen)
  3232. PreANSI(Pint *err)
  3233. /*
  3234. ** \parambegin
  3235. ** \param{Pint}{menuid}{menu identifier}{IN}
  3236. ** \param{Pint}{len}{length of string}{IN}
  3237. ** \param{char *}{titlestr}{title string of rotator banner}{IN}
  3238. ** \param{Pint *}{totlen}{actual length of string}{OUT}
  3239. ** \param{Pint *}{err}{error indicator}{OUT}
  3240. ** \paramend 
  3241. ** \blurb{This function may be used to obtain the title string of a rotator
  3242. ** menu. The error code = 1 if {\tt menuid} doesn't exist and = 2 if
  3243. ** the menu is not a rotator.}
  3244. */
  3245. {
  3246.   *err = 0;
  3247.   setmenu(menuid);
  3248.   if (menuptr != NULL)
  3249.   {  
  3250.     if (menuptr->menutype == PTKEROTATOR)
  3251.     {
  3252.       *totlen = strlen(menuptr->longstr) + 1;
  3253.       if (len >= *totlen)
  3254.         strncpy(titlestr, menuptr->longstr, *totlen);
  3255.     }
  3256.     else
  3257.       *err = 2;
  3258.   }
  3259.   else
  3260.     *err = 1;
  3261. }  /* ptk_inqrotatortitle */
  3262.  
  3263. /*--------------------------------------------------------------------------*/
  3264.  
  3265. /*function:external*/
  3266. extern void ptk_inqrotatorattrs(C(Pint) menuid, 
  3267.            C(Pint *) titlefont, C(Pint *) titlecolour, 
  3268.            C(Pint *) arrowcolour, C(Pint *) arrowedgecolour,
  3269.            C(Pint *) intcolour, C(Pint *) edgecolour, C(Pint *) bannercolour, 
  3270.            C(Pint *) boxtlcolour, C(Pint *) boxbrcolour, C(Pint *) err)
  3271. PreANSI(Pint menuid)
  3272. PreANSI(Pint *titlefont)
  3273. PreANSI(Pint *titlecolour)
  3274. PreANSI(Pint *arrowcolour)
  3275. PreANSI(Pint *arrowedgecolour)
  3276. PreANSI(Pint *intcolour)
  3277. PreANSI(Pint *edgecolour)
  3278. PreANSI(Pint *bannercolour)
  3279. PreANSI(Pint *boxtlcolour)
  3280. PreANSI(Pint *boxbrcolour)
  3281. PreANSI(Pint *err)
  3282. /*
  3283. ** \parambegin
  3284. ** \param{Pint}{menuid}{rotator identifier}{IN}
  3285. ** \param{Pint *}{titlefont}{title font}{OUT}
  3286. ** \param{Pint *}{titlecolour}{title colour index}{OUT}
  3287. ** \param{Pint *}{arrowcolour}{arrow interior colour index}{OUT}
  3288. ** \param{Pint *}{arrowedgecolour}{arrow edge colour index}{OUT}
  3289. ** \param{Pint *}{intcolour}{rotator interior colour index}{OUT}
  3290. ** \param{Pint *}{edgecolour}{edge colour index}{OUT}
  3291. ** \param{Pint *}{bannercolour}{banner colour index}{OUT}
  3292. ** \param{Pint *}{boxtlcolour}{top-left colour index}{OUT}
  3293. ** \param{Pint *}{boxbrcolour}{bottom-right colour index}{OUT}
  3294. ** \param{Pint *}{err}{error indicator}{OUT}
  3295. ** \paramend
  3296. ** \blurb{This function may be used to obtain the attribute values of
  3297. ** a rotator menu. The error code = 1 if {\tt menuid} doesn't exist and = 2 if
  3298. ** the menu is not a rotator.}
  3299. */
  3300. {
  3301.   *err = 0;
  3302.   setmenu(menuid);
  3303.   if (menuptr != NULL)
  3304.   {
  3305.     if (menuptr->menutype == PTKEROTATOR)
  3306.     {
  3307.       *titlefont = menuptr->font;
  3308.       *titlecolour = menuptr->textcolour;
  3309.       *intcolour = menuptr->intcolour;
  3310.       *edgecolour = menuptr->edgecolour;
  3311.       *boxtlcolour = menuptr->tlcolour;
  3312.       *boxbrcolour = menuptr->brcolour;
  3313.       *arrowcolour = menuptr->arrowcolour;
  3314.       *arrowedgecolour = menuptr->arrowedgecolour;
  3315.       *bannercolour = menuptr->bannercolour;
  3316.     }
  3317.     else
  3318.       *err = 2;
  3319.   }
  3320.   else
  3321.     *err = 1;
  3322. }  /* ptk_inqrotatorattrs */
  3323.  
  3324. /*--------------------------------------------------------------------------*/
  3325.  
  3326. /* end of menu.c */
  3327.